mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 02:31:34 +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)
|
- [Select](#version-7x-select)
|
||||||
- [Slides](#version-7x-slides)
|
- [Slides](#version-7x-slides)
|
||||||
- [Textarea](#version-7x-textarea)
|
- [Textarea](#version-7x-textarea)
|
||||||
|
- [Toggle](#version-7x-toggle)
|
||||||
- [Virtual Scroll](#version-7x-virtual-scroll)
|
- [Virtual Scroll](#version-7x-virtual-scroll)
|
||||||
- [JavaScript Frameworks](#version-7x-javascript-frameworks)
|
- [JavaScript Frameworks](#version-7x-javascript-frameworks)
|
||||||
- [React](#version-7x-react)
|
- [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"`.
|
- `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>
|
<h4 id="version-7x-virtual-scroll">Virtual Scroll</h4>
|
||||||
|
|
||||||
`ion-virtual-scroll` has been removed from Ionic.
|
`ion-virtual-scroll` has been removed from Ionic.
|
||||||
|
@ -1909,7 +1909,8 @@ export class IonTitle {
|
|||||||
import type { ToggleChangeEventDetail as IToggleToggleChangeEventDetail } from '@ionic/core';
|
import type { ToggleChangeEventDetail as IToggleToggleChangeEventDetail } from '@ionic/core';
|
||||||
export declare interface IonToggle extends Components.IonToggle {
|
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>>;
|
ionChange: EventEmitter<CustomEvent<IToggleToggleChangeEventDetail>>;
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ describe('Inputs', () => {
|
|||||||
cy.get('#reset-button').click();
|
cy.get('#reset-button').click();
|
||||||
|
|
||||||
cy.get('ion-checkbox#first-checkbox').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').eq(0).type('hola');
|
||||||
cy.get('ion-input input').eq(0).blur();
|
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;
|
"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;
|
"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 toggle = page.locator('#orange');
|
||||||
const ionChange = await page.spyOnEvent('ionChange');
|
const ionChange = await page.spyOnEvent('ionChange');
|
||||||
|
|
||||||
await toggle.evaluate((el: HTMLIonToggleElement) => (el.checked = true));
|
await toggle.evaluate((el: HTMLIonToggleElement) => (el.checked = true));
|
||||||
await page.waitForChanges();
|
await page.waitForChanges();
|
||||||
|
|
||||||
expect(ionChange).toHaveReceivedEvent();
|
expect(ionChange).toHaveReceivedEventTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should pass properties down to hidden input', async ({ page }) => {
|
test('should pass properties down to hidden input', async ({ page }) => {
|
||||||
|
@ -70,7 +70,8 @@ export class Toggle implements ComponentInterface {
|
|||||||
@Prop() enableOnOffLabels: boolean | undefined = undefined;
|
@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>;
|
@Event() ionChange!: EventEmitter<ToggleChangeEventDetail>;
|
||||||
|
|
||||||
@ -90,14 +91,6 @@ export class Toggle implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Event() ionStyle!: EventEmitter<StyleEventDetail>;
|
@Event() ionStyle!: EventEmitter<StyleEventDetail>;
|
||||||
|
|
||||||
@Watch('checked')
|
|
||||||
checkedChanged(isChecked: boolean) {
|
|
||||||
this.ionChange.emit({
|
|
||||||
checked: isChecked,
|
|
||||||
value: this.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Watch('disabled')
|
@Watch('disabled')
|
||||||
disabledChanged() {
|
disabledChanged() {
|
||||||
this.emitStyle();
|
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() {
|
async connectedCallback() {
|
||||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||||
el: this.el,
|
el: this.el,
|
||||||
@ -146,7 +151,7 @@ export class Toggle implements ComponentInterface {
|
|||||||
|
|
||||||
private onMove(detail: GestureDetail) {
|
private onMove(detail: GestureDetail) {
|
||||||
if (shouldToggle(isRTL(this.el), this.checked, detail.deltaX, -10)) {
|
if (shouldToggle(isRTL(this.el), this.checked, detail.deltaX, -10)) {
|
||||||
this.checked = !this.checked;
|
this.toggleChecked();
|
||||||
hapticSelection();
|
hapticSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +177,7 @@ export class Toggle implements ComponentInterface {
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
if (this.lastDrag + 300 < Date.now()) {
|
if (this.lastDrag + 300 < Date.now()) {
|
||||||
this.checked = !this.checked;
|
this.toggleChecked();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user