mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
feat(input): ionChange will only emit from user committed changes (#25858)
Resolves #20106, #20061
This commit is contained in:
@ -25,6 +25,6 @@ export class BooleanValueAccessorDirective extends ValueAccessor {
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any): void {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
this.handleValueChange(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
5
angular/src/directives/control-value-accessors/index.ts
Normal file
5
angular/src/directives/control-value-accessors/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './boolean-value-accessor';
|
||||
export * from './numeric-value-accessor';
|
||||
export * from './radio-value-accessor';
|
||||
export * from './select-value-accessor';
|
||||
export * from './text-value-accessor';
|
@ -18,13 +18,13 @@ export class NumericValueAccessorDirective extends ValueAccessor {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any): void {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
@HostListener('ionInput', ['$event.target'])
|
||||
handleInputEvent(el: HTMLIonInputElement): void {
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: number | null) => void): void {
|
||||
super.registerOnChange((value) => {
|
||||
super.registerOnChange((value: string) => {
|
||||
fn(value === '' ? null : parseFloat(value));
|
||||
});
|
||||
}
|
||||
|
@ -21,6 +21,6 @@ export class RadioValueAccessorDirective extends ValueAccessor {
|
||||
|
||||
@HostListener('ionSelect', ['$event.target'])
|
||||
_handleIonSelect(el: any): void {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
this.handleValueChange(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,6 @@ export class SelectValueAccessorDirective extends ValueAccessor {
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleChangeEvent(el: any): void {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { ValueAccessor } from './value-accessor';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-input:not([type=number]),ion-textarea,ion-searchbar',
|
||||
selector: 'ion-textarea,ion-searchbar',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
@ -21,6 +21,27 @@ export class TextValueAccessorDirective extends ValueAccessor {
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleInputEvent(el: any): void {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-input:not([type=number])',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: InputValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class InputValueAccessorDirective extends ValueAccessor {
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionInput', ['$event.target'])
|
||||
_handleInputEvent(el: any): void {
|
||||
this.handleValueChange(el, el.value);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,20 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
handleChangeEvent(el: HTMLElement, value: any): void {
|
||||
/**
|
||||
* Notifies the ControlValueAccessor of a change in the value of the control.
|
||||
*
|
||||
* This is called by each of the ValueAccessor directives when we want to update
|
||||
* the status and validity of the form control. For example with text components this
|
||||
* is called when the ionInput event is fired. For select components this is called
|
||||
* when the ionChange event is fired.
|
||||
*
|
||||
* This also updates the Ionic form status classes on the element.
|
||||
*
|
||||
* @param el The component element.
|
||||
* @param value The new value of the control.
|
||||
*/
|
||||
handleValueChange(el: HTMLElement, value: any): void {
|
||||
if (el === this.el.nativeElement) {
|
||||
if (value !== this.lastValue) {
|
||||
this.lastValue = value;
|
||||
|
@ -3,7 +3,10 @@ export { BooleanValueAccessorDirective as BooleanValueAccessor } from './directi
|
||||
export { NumericValueAccessorDirective as NumericValueAccessor } from './directives/control-value-accessors/numeric-value-accessor';
|
||||
export { RadioValueAccessorDirective as RadioValueAccessor } from './directives/control-value-accessors/radio-value-accessor';
|
||||
export { SelectValueAccessorDirective as SelectValueAccessor } from './directives/control-value-accessors/select-value-accessor';
|
||||
export { TextValueAccessorDirective as TextValueAccessor } from './directives/control-value-accessors/text-value-accessor';
|
||||
export {
|
||||
TextValueAccessorDirective as TextValueAccessor,
|
||||
InputValueAccessorDirective as InputValueAccessor,
|
||||
} from './directives/control-value-accessors/text-value-accessor';
|
||||
export { IonTabs } from './directives/navigation/ion-tabs';
|
||||
export { IonBackButtonDelegateDirective as IonBackButtonDelegate } from './directives/navigation/ion-back-button';
|
||||
export { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
|
@ -3,11 +3,14 @@ import { ModuleWithProviders, APP_INITIALIZER, NgModule, NgZone } from '@angular
|
||||
import { IonicConfig } from '@ionic/core';
|
||||
|
||||
import { appInitialize } from './app-initialize';
|
||||
import { BooleanValueAccessorDirective } from './directives/control-value-accessors/boolean-value-accessor';
|
||||
import { NumericValueAccessorDirective } from './directives/control-value-accessors/numeric-value-accessor';
|
||||
import { RadioValueAccessorDirective } from './directives/control-value-accessors/radio-value-accessor';
|
||||
import { SelectValueAccessorDirective } from './directives/control-value-accessors/select-value-accessor';
|
||||
import { TextValueAccessorDirective } from './directives/control-value-accessors/text-value-accessor';
|
||||
import {
|
||||
BooleanValueAccessorDirective,
|
||||
NumericValueAccessorDirective,
|
||||
RadioValueAccessorDirective,
|
||||
SelectValueAccessorDirective,
|
||||
TextValueAccessorDirective,
|
||||
InputValueAccessorDirective,
|
||||
} from './directives/control-value-accessors';
|
||||
import { IonBackButtonDelegateDirective } from './directives/navigation/ion-back-button';
|
||||
import { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
|
||||
import { IonTabs } from './directives/navigation/ion-tabs';
|
||||
@ -38,6 +41,7 @@ const DECLARATIONS = [
|
||||
RadioValueAccessorDirective,
|
||||
SelectValueAccessorDirective,
|
||||
TextValueAccessorDirective,
|
||||
InputValueAccessorDirective,
|
||||
|
||||
// navigation
|
||||
IonTabs,
|
||||
|
Reference in New Issue
Block a user