Skip to content

Commit c70432e

Browse files
authored
fix(checkbox, radio, toggle): disabled elements are not interactive (#28294)
Issue number: resolves #28293 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> Disabled toggles, radios, and checkboxes can still be enabled by manually dispatching a click event on them. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Toggles, radios, and checkboxes no longer activate if `disabled` is set to `true` ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev build: `7.4.4-dev.11696545130.1171e7a9`
1 parent a169044 commit c70432e

File tree

7 files changed

+83
-2
lines changed

7 files changed

+83
-2
lines changed

core/src/components/checkbox/checkbox.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ export class Checkbox implements ComponentInterface {
211211
};
212212

213213
private onClick = (ev: MouseEvent) => {
214+
if (this.disabled) {
215+
return;
216+
}
217+
214218
this.toggleChecked(ev);
215219
};
216220

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { newSpecPage } from '@stencil/core/testing';
2+
3+
import { Checkbox } from '../checkbox';
4+
5+
describe('ion-checkbox: disabled', () => {
6+
it('clicking disabled checkbox should not toggle checked state', async () => {
7+
const page = await newSpecPage({
8+
components: [Checkbox],
9+
html: `
10+
<ion-checkbox disabled="true">Checkbox</ion-checkbox>
11+
`,
12+
});
13+
14+
const checkbox = page.body.querySelector('ion-checkbox');
15+
16+
expect(checkbox.checked).toBe(false);
17+
18+
checkbox.click();
19+
20+
await page.waitForChanges();
21+
22+
expect(checkbox.checked).toBe(false);
23+
});
24+
});

core/src/components/radio-group/radio-group.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class RadioGroup implements ComponentInterface {
113113
* using the `name` attribute.
114114
*/
115115
const selectedRadio = ev.target && (ev.target as HTMLElement).closest('ion-radio');
116-
if (selectedRadio) {
116+
if (selectedRadio && selectedRadio.disabled === false) {
117117
const currentValue = this.value;
118118
const newValue = selectedRadio.value;
119119
if (newValue !== currentValue) {

core/src/components/radio/radio.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,11 @@ export class Radio implements ComponentInterface {
200200
};
201201

202202
private onClick = () => {
203-
const { radioGroup, checked } = this;
203+
const { radioGroup, checked, disabled } = this;
204+
205+
if (disabled) {
206+
return;
207+
}
204208

205209
/**
206210
* The legacy control uses a native input inside

core/src/components/radio/test/radio.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,27 @@ describe('ion-radio', () => {
3131
expect(radio.classList.contains('radio-checked')).toBe(true);
3232
});
3333
});
34+
35+
describe('ion-radio: disabled', () => {
36+
it('clicking disabled radio should not set checked state', async () => {
37+
const page = await newSpecPage({
38+
components: [Radio, RadioGroup],
39+
html: `
40+
<ion-radio-group>
41+
<ion-radio disabled="true" value="a">Radio</ion-radio>
42+
</ion-radio-group>
43+
`,
44+
});
45+
46+
const radio = page.body.querySelector('ion-radio');
47+
const radioGroup = page.body.querySelector('ion-radio-group');
48+
49+
expect(radioGroup.value).toBe(undefined);
50+
51+
radio.click();
52+
53+
await page.waitForChanges();
54+
55+
expect(radioGroup.value).toBe(undefined);
56+
});
57+
});

core/src/components/toggle/test/toggle.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,24 @@ describe('toggle', () => {
4141
});
4242
});
4343
});
44+
45+
describe('ion-toggle: disabled', () => {
46+
it('clicking disabled toggle should not toggle checked state', async () => {
47+
const page = await newSpecPage({
48+
components: [Toggle],
49+
html: `
50+
<ion-toggle disabled="true">Toggle</ion-toggle>
51+
`,
52+
});
53+
54+
const toggle = page.body.querySelector('ion-toggle');
55+
56+
expect(toggle.checked).toBe(false);
57+
58+
toggle.click();
59+
60+
await page.waitForChanges();
61+
62+
expect(toggle.checked).toBe(false);
63+
});
64+
});

core/src/components/toggle/toggle.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ export class Toggle implements ComponentInterface {
259259
}
260260

261261
private onClick = (ev: MouseEvent) => {
262+
if (this.disabled) {
263+
return;
264+
}
265+
262266
ev.preventDefault();
263267

264268
if (this.lastDrag + 300 < Date.now()) {

0 commit comments

Comments
 (0)