fix(forms): number input fires valueChanges twice. (#36087)
Prior to this commit, number input fields would to fire valueChanges twice: once for `input` events when typing and second for the `change` event when the field lost focus (both events happen at once when using the increment and decrement buttons on the number field). Fixes #12540 BREAKING CHANGE: Number inputs no longer listen to the `change` event. * Tests which trigger `change` events need to be updated to trigger `input` events instead. * The `change` event was in place to support IE9, as we found that `input` events were not fired with backspace or cut actions. If you need to maintain IE9 support, you will need to add a change event listener to number inputs and call the `onChange` method of `NumberValueAccessor` manually. * Lastly, old versions of WebDriver would synthetically trigger the `change` event on `WebElement.clear` and `WebElement.sendKeys`. If you are using an old version of WebDriver, you may need to update tests to ensure `input` events are triggered. For example, you could use `element.sendKeys(Keys.chord(Keys.CONTROL, "a"), Keys.BACK_SPACE);` in place of `element.clear()`. PR Close #12540 PR Close #36087
This commit is contained in:
parent
f7815cf96d
commit
97d6d909e7
|
@ -43,11 +43,7 @@ export const NUMBER_VALUE_ACCESSOR: any = {
|
||||||
@Directive({
|
@Directive({
|
||||||
selector:
|
selector:
|
||||||
'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]',
|
'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]',
|
||||||
host: {
|
host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
|
||||||
'(change)': 'onChange($event.target.value)',
|
|
||||||
'(input)': 'onChange($event.target.value)',
|
|
||||||
'(blur)': 'onTouched()'
|
|
||||||
},
|
|
||||||
providers: [NUMBER_VALUE_ACCESSOR]
|
providers: [NUMBER_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class NumberValueAccessor implements ControlValueAccessor {
|
export class NumberValueAccessor implements ControlValueAccessor {
|
||||||
|
|
|
@ -149,6 +149,23 @@ import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util'
|
||||||
expect(control.value).toEqual(0);
|
expect(control.value).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore the change event', () => {
|
||||||
|
const fixture = initTest(FormControlNumberInput);
|
||||||
|
const control = new FormControl();
|
||||||
|
fixture.componentInstance.control = control;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
control.valueChanges.subscribe({
|
||||||
|
next: (value) => {
|
||||||
|
throw 'Input[number] should not react to change event';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const input = fixture.debugElement.query(By.css('input'));
|
||||||
|
|
||||||
|
input.nativeElement.value = '5';
|
||||||
|
dispatchEvent(input.nativeElement, 'change');
|
||||||
|
});
|
||||||
|
|
||||||
it('when value is cleared programmatically', () => {
|
it('when value is cleared programmatically', () => {
|
||||||
const fixture = initTest(FormControlNumberInput);
|
const fixture = initTest(FormControlNumberInput);
|
||||||
const control = new FormControl(10);
|
const control = new FormControl(10);
|
||||||
|
|
Loading…
Reference in New Issue