Skip to content

Commit e6e2e77

Browse files
Fixing Dynamic Checkbox and radio button misbehaviour. (#1711)
1 parent 0182591 commit e6e2e77

File tree

12 files changed

+741
-34
lines changed

12 files changed

+741
-34
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
3+
jcr:primaryType="sling:Folder"
4+
lcFolder="{Long}0"
5+
type="lcFolder">
6+
<jcr:content
7+
jcr:primaryType="nt:unstructured"
8+
jcr:title="dynamicEnumEnumNames">
9+
<folderThumbnail/>
10+
</jcr:content>
11+
</jcr:root>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
3+
jcr:primaryType="nt:file">
4+
<jcr:content jcr:primaryType="nt:unstructured"/>
5+
</jcr:root>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:dam="http://www.day.com/dam/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:fd="http://www.adobe.com/aemfd/fd/1.0"
3+
jcr:primaryType="dam:Asset">
4+
<jcr:content
5+
cq:conf="\0"
6+
jcr:lastModified="{Date}2025-09-15T12:32:32.278+05:30"
7+
jcr:primaryType="dam:AssetContent"
8+
sling:resourceType="fd/fm/af/render"
9+
guide="1"
10+
type="guide">
11+
<metadata
12+
fd:version="2.1"
13+
jcr:language="en"
14+
jcr:primaryType="nt:unstructured"
15+
xmp:CreatorTool="AEM Forms AF Wizard"
16+
allowedRenderFormat="HTML"
17+
author="admin"
18+
dorType="none"
19+
formmodel="none"
20+
themeRef="/libs/fd/af/themes/canvas"
21+
title="dynamicOptions"/>
22+
</jcr:content>
23+
</jcr:root>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
3+
jcr:primaryType="sling:Folder"/>

it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/dynamicenumenumnames/dynamicoptions/.content.xml

Lines changed: 298 additions & 0 deletions
Large diffs are not rendered by default.

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/checkboxgroup/v1/checkboxgroup/checkboxgroup.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
~ See the License for the specific language governing permissions and
1414
~ limitations under the License.
1515
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
16+
<!--//TOFIX: Rich text in aria-label!-->
1617
<sly data-sly-use.renderer="${'checkboxgroup.js'}"
1718
data-sly-use.widget="widget.html"
1819
data-sly-use.clientlib="${'/libs/granite/sightly/templates/clientlib.html'}"

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/checkboxgroup/v1/checkboxgroup/clientlibs/site/js/checkboxgroupview.js

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,23 @@
8282
return this.element.querySelectorAll(CheckBoxGroup.selectors.item);
8383
}
8484

85+
#addWidgetListeners(optionWidget) {
86+
optionWidget.addEventListener('change', (e) => {
87+
this.#updateModelValue(optionWidget);
88+
});
89+
optionWidget.addEventListener('focus', (e) => {
90+
this.setActive();
91+
});
92+
optionWidget.addEventListener('blur', (e) => {
93+
this.setInactive();
94+
});
95+
}
96+
8597
setModel(model) {
8698
super.setModel(model);
87-
let widgets = this.widget;
88-
widgets.forEach(widget => {
89-
let self = widget;
90-
this.#updateModelValue(self);
91-
widget.addEventListener('change', (e) => {
92-
this.#updateModelValue(self);
93-
});
94-
widget.addEventListener('focus', (e) => {
95-
this.setActive();
96-
});
97-
widget.addEventListener('blur', (e) => {
98-
this.setInactive();
99-
});
100-
})
101-
99+
this.widget.forEach(optionWidget => {
100+
this.#addWidgetListeners(optionWidget);
101+
});
102102
let optionLinks = this.element.querySelectorAll(`.${CheckBoxGroup.selectors.optionLink}`);
103103
const actionKeys = ['Enter', ' ', 'Spacebar', 'Space'];
104104
optionLinks.forEach(optionLink => {
@@ -108,9 +108,10 @@
108108
}
109109
});
110110
});
111+
this.#updateModelValue();
111112
}
112113

113-
#updateModelValue(widget) {
114+
#updateModelValue() {
114115
let value = [];
115116
this.widget.forEach(widget => {
116117
if (widget.checked) {
@@ -148,24 +149,38 @@
148149
}
149150

150151
#createCheckBoxItem(value, itemLabel) {
152+
// This doesn't cater for optionLink __links as toggelablelink component is hidden
153+
//TOFIX: Rich text in aria-label
151154
const optionTemplate = `
152155
<div class="${CheckBoxGroup.selectors.item.slice(1)}">
153-
<label class="${CheckBoxGroup.selectors.optionLabel.slice(1)}">
154-
<input type="checkbox" class="${CheckBoxGroup.selectors.widget.slice(1)}" value="${value}">
156+
<label class="${CheckBoxGroup.selectors.optionLabel}">
157+
<input type="checkbox" class="${CheckBoxGroup.selectors.widget.slice(1)}" name="${this._model.name}" value="${value}" aria-label="${this._model.label.value}: ${itemLabel}" tabindex="0">
155158
<span>${itemLabel}</span>
156159
</label>
157160
</div>`;
158161

159162
const container = document.createElement('div'); // Create a container element to hold the template
160163
container.innerHTML = optionTemplate;
164+
let addedOptionWidget = container.querySelector(CheckBoxGroup.selectors.widget);
165+
if(this._model.readOnly === true || this._model.enabled === false) {
166+
addedOptionWidget.setAttribute("disabled", true);
167+
if(this._model.readOnly === true) {
168+
addedOptionWidget.setAttribute("aria-readonly", true);
169+
}
170+
}
171+
this.#addWidgetListeners(addedOptionWidget);
161172
return container.firstElementChild; // Return the first child, which is the created option
162173
}
163174
updateEnum(newEnums) {
164175
super.updateEnumForRadioButtonAndCheckbox(newEnums, this.#createCheckBoxItem);
176+
// refresh the widget references, to dynamically added options
177+
this.widget = this.getWidget();
165178
}
166179

167180
updateEnumNames(newEnumNames) {
168181
super.updateEnumNamesForRadioButtonAndCheckbox(newEnumNames, this.#createCheckBoxItem);
182+
// refresh the widget references, to dynamically added options
183+
this.widget = this.getWidget();
169184
}
170185

171186
updateEnabled(enabled, state) {

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/checkboxgroup/v1/checkboxgroup/widget.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
~ See the License for the specific language governing permissions and
1414
~ limitations under the License.
1515
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
16+
<!--//TOFIX: Rich text in aria-label!-->
1617
<template data-sly-template.widget="${ @ checkboxgroup }">
1718
<div class="cmp-adaptiveform-checkboxgroup__widget ${checkboxgroup.orientation}" id="${widgetId}">
1819
<div data-sly-list="${checkboxgroup.enums}" data-sly-unwrap>

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/clientlibs/site/js/radiobuttonview.js

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,22 @@
7777
return this.element.querySelectorAll(RadioButton.selectors.option);
7878
}
7979

80+
#addWidgetListeners(optionWidget) {
81+
optionWidget.addEventListener('change', (e) => {
82+
this.setModelValue(e.target.value);
83+
});
84+
optionWidget.addEventListener('focus', (e) => {
85+
this.setActive();
86+
});
87+
optionWidget.addEventListener('blur', (e) => {
88+
this.setInactive();
89+
});
90+
}
91+
8092
setModel(model) {
8193
super.setModel(model);
82-
let widgets = this.widget;
83-
widgets.forEach(widget => {
84-
widget.addEventListener('change', (e) => {
85-
this.setModelValue(e.target.value);
86-
});
87-
widget.addEventListener('focus', (e) => {
88-
this.setActive();
89-
});
90-
widget.addEventListener('blur', (e) => {
91-
this.setInactive();
92-
});
94+
this.widget.forEach(optionWidget => {
95+
this.#addWidgetListeners(optionWidget);
9396
});
9497
}
9598

@@ -143,25 +146,38 @@
143146
}
144147

145148
#createRadioOption(value, itemLabel) {
149+
//TOFIX: Rich text in aria-label
146150
const optionTemplate = `
147151
<div class="${RadioButton.selectors.option.slice(1)}">
148152
<label class="${RadioButton.selectors.optionLabel.slice(1)}">
149-
<input type="checkbox" class="${RadioButton.selectors.widget.slice(1)}" value="${value}">
153+
<input type="radio" name="${this._model.name}" class="${RadioButton.selectors.widget.slice(1)}" value="${value}" aria-label="${this._model.label.value}: ${itemLabel}" tabindex="0">
150154
<span>${itemLabel}</span>
151155
</label>
152156
</div>`;
153157

154158
const container = document.createElement('div'); // Create a container element to hold the template
155159
container.innerHTML = optionTemplate;
160+
let addedOptionWidget = container.querySelector(RadioButton.selectors.widget);
161+
if(this._model.readOnly === true || this._model.enabled === false) {
162+
addedOptionWidget.setAttribute("disabled", true);
163+
if(this._model.readOnly === true) {
164+
addedOptionWidget.setAttribute("aria-readonly", true);
165+
}
166+
}
167+
this.#addWidgetListeners(addedOptionWidget);
156168
return container.firstElementChild; // Return the first child, which is the created option
157169
}
158170

159171
updateEnum(newEnums) {
160172
super.updateEnumForRadioButtonAndCheckbox(newEnums, this.#createRadioOption);
173+
// refresh the widget references, to dynamically added options
174+
this.widget = this.getWidget();
161175
}
162176

163177
updateEnumNames(newEnumNames) {
164-
super.updateEnumNamesForRadioButtonAndCheckbox(newEnumNames, this.#createRadioOption)
178+
super.updateEnumNamesForRadioButtonAndCheckbox(newEnumNames, this.#createRadioOption);
179+
// refresh the widget references, to dynamically added options
180+
this.widget = this.getWidget();
165181
}
166182

167183
updateRequired(required, state) {

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/radiobutton/v1/radiobutton/radiobutton.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
~ See the License for the specific language governing permissions and
1414
~ limitations under the License.
1515
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
16-
16+
<!--//TOFIX: Rich text in aria-label!-->
1717
<sly data-sly-use.renderer="${'radiobutton.js'}"
1818
data-sly-use.clientlib="${'/libs/granite/sightly/templates/clientlib.html'}"
1919
data-sly-use.label="${renderer.labelPath}"
@@ -49,6 +49,7 @@
4949
value="${item.toString}"
5050
disabled="${!radioButton.enabled || radioButton.readOnly}"
5151
checked="${radioButton.enums[itemList.index] == radioButton.default[0]}"
52+
aria-readonly="${radioButton.readOnly ? 'true' : ''}"
5253
aria-label="${radioButton.label.value}: ${radioButton.enumNames[itemList.index]}" tabindex="0"/>
5354
<span>${radioButton.enumNames[itemList.index] @ context = 'html'}</span>
5455
</label>

0 commit comments

Comments
 (0)