Skip to content

Commit 40488c1

Browse files
authored
feat: add readonly property to checkbox and checkbox-group (#7199)
1 parent 67b4033 commit 40488c1

28 files changed

+445
-71
lines changed

packages/checkbox-group/src/vaadin-checkbox-group-mixin.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,12 @@ export declare class CheckboxGroupMixinClass {
3333
* creating a new array.
3434
*/
3535
value: string[];
36+
37+
/**
38+
* When true, the user cannot modify the value of the checkbox group.
39+
* The difference between `disabled` and `readonly` is that in the
40+
* read-only checkbox group, all the checkboxes are also read-only,
41+
* and therefore remain focusable and announced by screen readers.
42+
*/
43+
readonly: boolean;
3644
}

packages/checkbox-group/src/vaadin-checkbox-group-mixin.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ export const CheckboxGroupMixin = (superclass) =>
3636
notify: true,
3737
observer: '__valueChanged',
3838
},
39+
40+
/**
41+
* When true, the user cannot modify the value of the checkbox group.
42+
* The difference between `disabled` and `readonly` is that in the
43+
* read-only checkbox group, all the checkboxes are also read-only,
44+
* and therefore remain focusable and announced by screen readers.
45+
*/
46+
readonly: {
47+
type: Boolean,
48+
value: false,
49+
reflectToAttribute: true,
50+
observer: '__readonlyChanged',
51+
},
3952
};
4053
}
4154

@@ -145,6 +158,10 @@ export const CheckboxGroupMixin = (superclass) =>
145158
checkbox.disabled = true;
146159
}
147160

161+
if (this.readonly) {
162+
checkbox.readonly = true;
163+
}
164+
148165
if (checkbox.checked) {
149166
this.__addCheckboxToValue(checkbox.value);
150167
} else if (this.value.includes(checkbox.value)) {
@@ -248,6 +265,15 @@ export const CheckboxGroupMixin = (superclass) =>
248265
}
249266
}
250267

268+
/** @private */
269+
__readonlyChanged(readonly, oldReadonly) {
270+
if (readonly || oldReadonly) {
271+
this.__checkboxes.forEach((checkbox) => {
272+
checkbox.readonly = readonly;
273+
});
274+
}
275+
}
276+
251277
/**
252278
* Override method inherited from `FocusMixin`
253279
* to prevent removing the `focused` attribute

packages/checkbox-group/test/checkbox-group.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,38 @@ describe('vaadin-checkbox-group', () => {
8484
});
8585
});
8686

87+
describe('readonly', () => {
88+
beforeEach(async () => {
89+
group = fixtureSync(`
90+
<vaadin-checkbox-group readonly>
91+
<vaadin-checkbox value="1" label="Checkbox 1"></vaadin-checkbox>
92+
<vaadin-checkbox value="2" label="Checkbox 2"></vaadin-checkbox>
93+
</vaadin-checkbox-group>
94+
`);
95+
await nextFrame();
96+
checkboxes = [...group.querySelectorAll('vaadin-checkbox')];
97+
});
98+
99+
it('should propagate readonly property to checkboxes', () => {
100+
checkboxes.forEach((checkbox) => {
101+
expect(checkbox.readonly).to.be.true;
102+
});
103+
104+
group.readonly = false;
105+
checkboxes.forEach((checkbox) => {
106+
expect(checkbox.readonly).to.be.false;
107+
});
108+
});
109+
110+
it('should set readonly property to dynamically added checkboxes', async () => {
111+
const checkbox = document.createElement('vaadin-checkbox');
112+
checkbox.value = '3';
113+
group.appendChild(checkbox);
114+
await nextFrame();
115+
expect(checkbox.readonly).to.be.true;
116+
});
117+
});
118+
87119
describe('value', () => {
88120
beforeEach(async () => {
89121
group = fixtureSync(`

packages/checkbox-group/test/dom/__snapshots__/checkbox-group.test.snap.js

Lines changed: 100 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,70 @@ snapshots["vaadin-checkbox-group host default"] =
6060
`;
6161
/* end snapshot vaadin-checkbox-group host default */
6262

63+
snapshots["vaadin-checkbox-group host label"] =
64+
`<vaadin-checkbox-group
65+
aria-labelledby="label-vaadin-checkbox-group-0"
66+
has-label=""
67+
role="group"
68+
>
69+
<vaadin-checkbox
70+
has-label=""
71+
has-value=""
72+
label="Checkbox 1"
73+
value="1"
74+
>
75+
<label
76+
for="input-vaadin-checkbox-5"
77+
id="label-vaadin-checkbox-3"
78+
slot="label"
79+
>
80+
Checkbox 1
81+
</label>
82+
<input
83+
id="input-vaadin-checkbox-5"
84+
slot="input"
85+
tabindex="0"
86+
type="checkbox"
87+
value="1"
88+
>
89+
</vaadin-checkbox>
90+
<vaadin-checkbox
91+
has-label=""
92+
has-value=""
93+
label="Checkbox 2"
94+
value="2"
95+
>
96+
<label
97+
for="input-vaadin-checkbox-6"
98+
id="label-vaadin-checkbox-4"
99+
slot="label"
100+
>
101+
Checkbox 2
102+
</label>
103+
<input
104+
id="input-vaadin-checkbox-6"
105+
slot="input"
106+
tabindex="0"
107+
type="checkbox"
108+
value="2"
109+
>
110+
</vaadin-checkbox>
111+
<label
112+
id="label-vaadin-checkbox-group-0"
113+
slot="label"
114+
>
115+
Label
116+
</label>
117+
<div
118+
hidden=""
119+
id="error-message-vaadin-checkbox-group-2"
120+
slot="error-message"
121+
>
122+
</div>
123+
</vaadin-checkbox-group>
124+
`;
125+
/* end snapshot vaadin-checkbox-group host label */
126+
63127
snapshots["vaadin-checkbox-group host disabled"] =
64128
`<vaadin-checkbox-group
65129
aria-disabled="true"
@@ -129,45 +193,16 @@ snapshots["vaadin-checkbox-group host disabled"] =
129193
`;
130194
/* end snapshot vaadin-checkbox-group host disabled */
131195

132-
snapshots["vaadin-checkbox-group shadow default"] =
133-
`<div class="vaadin-group-field-container">
134-
<div part="label">
135-
<slot name="label">
136-
</slot>
137-
<span
138-
aria-hidden="true"
139-
part="required-indicator"
140-
>
141-
</span>
142-
</div>
143-
<div part="group-field">
144-
<slot>
145-
</slot>
146-
</div>
147-
<div part="helper-text">
148-
<slot name="helper">
149-
</slot>
150-
</div>
151-
<div part="error-message">
152-
<slot name="error-message">
153-
</slot>
154-
</div>
155-
</div>
156-
<slot name="tooltip">
157-
</slot>
158-
`;
159-
/* end snapshot vaadin-checkbox-group shadow default */
160-
161-
snapshots["vaadin-checkbox-group host label"] =
196+
snapshots["vaadin-checkbox-group host readonly"] =
162197
`<vaadin-checkbox-group
163-
aria-labelledby="label-vaadin-checkbox-group-0"
164-
has-label=""
198+
readonly=""
165199
role="group"
166200
>
167201
<vaadin-checkbox
168202
has-label=""
169203
has-value=""
170204
label="Checkbox 1"
205+
readonly=""
171206
value="1"
172207
>
173208
<label
@@ -178,6 +213,7 @@ snapshots["vaadin-checkbox-group host label"] =
178213
Checkbox 1
179214
</label>
180215
<input
216+
aria-readonly="true"
181217
id="input-vaadin-checkbox-5"
182218
slot="input"
183219
tabindex="0"
@@ -189,6 +225,7 @@ snapshots["vaadin-checkbox-group host label"] =
189225
has-label=""
190226
has-value=""
191227
label="Checkbox 2"
228+
readonly=""
192229
value="2"
193230
>
194231
<label
@@ -199,6 +236,7 @@ snapshots["vaadin-checkbox-group host label"] =
199236
Checkbox 2
200237
</label>
201238
<input
239+
aria-readonly="true"
202240
id="input-vaadin-checkbox-6"
203241
slot="input"
204242
tabindex="0"
@@ -210,7 +248,6 @@ snapshots["vaadin-checkbox-group host label"] =
210248
id="label-vaadin-checkbox-group-0"
211249
slot="label"
212250
>
213-
Label
214251
</label>
215252
<div
216253
hidden=""
@@ -220,7 +257,7 @@ snapshots["vaadin-checkbox-group host label"] =
220257
</div>
221258
</vaadin-checkbox-group>
222259
`;
223-
/* end snapshot vaadin-checkbox-group host label */
260+
/* end snapshot vaadin-checkbox-group host readonly */
224261

225262
snapshots["vaadin-checkbox-group host required"] =
226263
`<vaadin-checkbox-group
@@ -419,3 +456,32 @@ snapshots["vaadin-checkbox-group host error"] =
419456
`;
420457
/* end snapshot vaadin-checkbox-group host error */
421458

459+
snapshots["vaadin-checkbox-group shadow default"] =
460+
`<div class="vaadin-group-field-container">
461+
<div part="label">
462+
<slot name="label">
463+
</slot>
464+
<span
465+
aria-hidden="true"
466+
part="required-indicator"
467+
>
468+
</span>
469+
</div>
470+
<div part="group-field">
471+
<slot>
472+
</slot>
473+
</div>
474+
<div part="helper-text">
475+
<slot name="helper">
476+
</slot>
477+
</div>
478+
<div part="error-message">
479+
<slot name="error-message">
480+
</slot>
481+
</div>
482+
</div>
483+
<slot name="tooltip">
484+
</slot>
485+
`;
486+
/* end snapshot vaadin-checkbox-group shadow default */
487+

packages/checkbox-group/test/dom/checkbox-group.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ describe('vaadin-checkbox-group', () => {
3131
await expect(group).dom.to.equalSnapshot();
3232
});
3333

34+
it('readonly', async () => {
35+
group.readonly = true;
36+
await expect(group).dom.to.equalSnapshot();
37+
});
38+
3439
it('required', async () => {
3540
group.required = true;
3641
await expect(group).dom.to.equalSnapshot();

packages/checkbox-group/test/visual/lumo/checkbox-group.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ describe('checkbox-group', () => {
6060
await visualDiff(div, 'value');
6161
});
6262

63+
it('readonly', async () => {
64+
element.readonly = true;
65+
element.value = ['a', 'c'];
66+
await visualDiff(div, 'readonly');
67+
});
68+
6369
it('required', async () => {
6470
element.label = 'Label';
6571
element.required = true;
Loading

packages/checkbox-group/test/visual/material/checkbox-group.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ describe('checkbox-group', () => {
6060
await visualDiff(div, 'value');
6161
});
6262

63+
it('readonly', async () => {
64+
element.readonly = true;
65+
element.value = ['a', 'c'];
66+
await visualDiff(div, 'readonly');
67+
});
68+
6369
it('required', async () => {
6470
element.label = 'Label';
6571
element.required = true;
Loading

packages/checkbox/src/vaadin-checkbox-mixin.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,12 @@ export declare class CheckboxMixinClass {
4747
* The name of the checkbox.
4848
*/
4949
name: string;
50+
51+
/**
52+
* When true, the user cannot modify the value of the checkbox.
53+
* The difference between `disabled` and `readonly` is that the
54+
* read-only checkbox remains focusable, is announced by screen
55+
* readers and its value can be submitted as part of the form.
56+
*/
57+
readonly: boolean;
5058
}

0 commit comments

Comments
 (0)