mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 18:17:31 +08:00
feat(toggle): ionChange will only emit from user committed changes (#26078)
Co-authored-by: Sean Perkins <sean@ionic.io>
This commit is contained in:
@ -25,6 +25,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
|
||||
- [Select](#version-7x-select)
|
||||
- [Slides](#version-7x-slides)
|
||||
- [Textarea](#version-7x-textarea)
|
||||
- [Toggle](#version-7x-toggle)
|
||||
- [Virtual Scroll](#version-7x-virtual-scroll)
|
||||
- [JavaScript Frameworks](#version-7x-javascript-frameworks)
|
||||
- [React](#version-7x-react)
|
||||
@ -147,6 +148,10 @@ Developers using these components will need to migrate to using Swiper.js direct
|
||||
|
||||
- `ionInput` dispatches an event detail of `null` when the textarea is cleared as a result of `clear-on-edit="true"`.
|
||||
|
||||
<h4 id="version-7x-toggle">Toggle</h4>
|
||||
|
||||
- `ionChange` is no longer emitted when the `checked` property of `ion-toggle` is modified externally. `ionChange` is only emitted from user committed changes, such as clicking the toggle to set it on or off.
|
||||
|
||||
<h4 id="version-7x-virtual-scroll">Virtual Scroll</h4>
|
||||
|
||||
`ion-virtual-scroll` has been removed from Ionic.
|
||||
|
@ -1909,7 +1909,8 @@ export class IonTitle {
|
||||
import type { ToggleChangeEventDetail as IToggleToggleChangeEventDetail } from '@ionic/core';
|
||||
export declare interface IonToggle extends Components.IonToggle {
|
||||
/**
|
||||
* Emitted when the value property has changed.
|
||||
* Emitted when the user switches the toggle on or off. Does not emit
|
||||
when programmatically changing the value of the `checked` property.
|
||||
*/
|
||||
ionChange: EventEmitter<CustomEvent<IToggleToggleChangeEventDetail>>;
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ describe('Inputs', () => {
|
||||
cy.get('#reset-button').click();
|
||||
|
||||
cy.get('ion-checkbox#first-checkbox').click();
|
||||
cy.get('ion-toggle').invoke('prop', 'checked', true);
|
||||
cy.get('ion-toggle').first().click();
|
||||
|
||||
cy.get('ion-input').eq(0).type('hola');
|
||||
cy.get('ion-input input').eq(0).blur();
|
||||
|
2
core/src/components.d.ts
vendored
2
core/src/components.d.ts
vendored
@ -6725,7 +6725,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"onIonBlur"?: (event: IonToggleCustomEvent<void>) => void;
|
||||
/**
|
||||
* Emitted when the value property has changed.
|
||||
* Emitted when the user switches the toggle on or off. Does not emit when programmatically changing the value of the `checked` property.
|
||||
*/
|
||||
"onIonChange"?: (event: IonToggleCustomEvent<ToggleChangeEventDetail>) => void;
|
||||
/**
|
||||
|
@ -52,14 +52,14 @@ test.describe('toggle: basic', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('should fire change event if checked prop is changed directly', async ({ page }) => {
|
||||
test('should not fire change event if checked prop is changed directly', async ({ page }) => {
|
||||
const toggle = page.locator('#orange');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
await toggle.evaluate((el: HTMLIonToggleElement) => (el.checked = true));
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(ionChange).toHaveReceivedEvent();
|
||||
expect(ionChange).toHaveReceivedEventTimes(0);
|
||||
});
|
||||
|
||||
test('should pass properties down to hidden input', async ({ page }) => {
|
||||
|
@ -70,7 +70,8 @@ export class Toggle implements ComponentInterface {
|
||||
@Prop() enableOnOffLabels: boolean | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Emitted when the value property has changed.
|
||||
* Emitted when the user switches the toggle on or off. Does not emit
|
||||
* when programmatically changing the value of the `checked` property.
|
||||
*/
|
||||
@Event() ionChange!: EventEmitter<ToggleChangeEventDetail>;
|
||||
|
||||
@ -90,14 +91,6 @@ export class Toggle implements ComponentInterface {
|
||||
*/
|
||||
@Event() ionStyle!: EventEmitter<StyleEventDetail>;
|
||||
|
||||
@Watch('checked')
|
||||
checkedChanged(isChecked: boolean) {
|
||||
this.ionChange.emit({
|
||||
checked: isChecked,
|
||||
value: this.value,
|
||||
});
|
||||
}
|
||||
|
||||
@Watch('disabled')
|
||||
disabledChanged() {
|
||||
this.emitStyle();
|
||||
@ -106,6 +99,18 @@ export class Toggle implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private toggleChecked() {
|
||||
const { checked, value } = this;
|
||||
|
||||
const isNowChecked = !checked;
|
||||
this.checked = isNowChecked;
|
||||
|
||||
this.ionChange.emit({
|
||||
checked: isNowChecked,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
el: this.el,
|
||||
@ -146,7 +151,7 @@ export class Toggle implements ComponentInterface {
|
||||
|
||||
private onMove(detail: GestureDetail) {
|
||||
if (shouldToggle(isRTL(this.el), this.checked, detail.deltaX, -10)) {
|
||||
this.checked = !this.checked;
|
||||
this.toggleChecked();
|
||||
hapticSelection();
|
||||
}
|
||||
}
|
||||
@ -172,7 +177,7 @@ export class Toggle implements ComponentInterface {
|
||||
ev.preventDefault();
|
||||
|
||||
if (this.lastDrag + 300 < Date.now()) {
|
||||
this.checked = !this.checked;
|
||||
this.toggleChecked();
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user