parent
c7245189e2
commit
c5ea03a023
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Directive, Host, Inject, Input, OnChanges, OnDestroy, Optional, Output, Self, SimpleChanges, forwardRef} from '@angular/core';
|
||||
import {Directive, Host, HostListener, Inject, Input, OnChanges, OnDestroy, Optional, Output, Self, SimpleChanges, forwardRef} from '@angular/core';
|
||||
|
||||
import {EventEmitter} from '../facade/async';
|
||||
import {FormControl} from '../model';
|
||||
|
@ -115,6 +115,7 @@ export class NgModel extends NgControl implements OnChanges,
|
|||
_control = new FormControl();
|
||||
/** @internal */
|
||||
_registered = false;
|
||||
private _composing = false;
|
||||
viewModel: any;
|
||||
|
||||
@Input() name: string;
|
||||
|
@ -124,6 +125,15 @@ export class NgModel extends NgControl implements OnChanges,
|
|||
|
||||
@Output('ngModelChange') update = new EventEmitter();
|
||||
|
||||
@HostListener('compositionstart')
|
||||
compositionStart(): void { this._composing = true; }
|
||||
|
||||
@HostListener('compositionend')
|
||||
compositionEnd(): void {
|
||||
this._composing = false;
|
||||
this.update.emit(this.viewModel);
|
||||
}
|
||||
|
||||
constructor(@Optional() @Host() parent: ControlContainer,
|
||||
@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
|
||||
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<Validator|AsyncValidatorFn>,
|
||||
|
@ -167,7 +177,7 @@ export class NgModel extends NgControl implements OnChanges,
|
|||
|
||||
viewToModelUpdate(newValue: any): void {
|
||||
this.viewModel = newValue;
|
||||
this.update.emit(newValue);
|
||||
!this._composing && this.update.emit(newValue);
|
||||
}
|
||||
|
||||
private _setUpControl(): void {
|
||||
|
|
|
@ -42,6 +42,39 @@ export function main() {
|
|||
expect(fixture.componentInstance.name).toEqual('updatedValue');
|
||||
}));
|
||||
|
||||
it('should ngModel hold ime events until compositionend', fakeAsync(() => {
|
||||
const fixture = TestBed.createComponent(StandaloneNgModel);
|
||||
// model -> view
|
||||
const inputEl = fixture.debugElement.query(By.css('input'));
|
||||
const inputNativeEl = inputEl.nativeElement;
|
||||
|
||||
fixture.componentInstance.name = 'oldValue';
|
||||
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(inputNativeEl.value).toEqual('oldValue');
|
||||
// view -> model
|
||||
inputEl.triggerEventHandler('compositionstart', null);
|
||||
|
||||
inputNativeEl.value = 'updatedValue';
|
||||
dispatchEvent(inputNativeEl, 'input');
|
||||
tick();
|
||||
|
||||
// should ngModel not update when compositionstart
|
||||
|
||||
expect(fixture.componentInstance.name).toEqual('oldValue');
|
||||
|
||||
inputEl.triggerEventHandler('compositionend', null);
|
||||
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
// should ngModel update when compositionend
|
||||
|
||||
expect(fixture.componentInstance.name).toEqual('updatedValue');
|
||||
}));
|
||||
|
||||
it('should support ngModel registration with a parent form', fakeAsync(() => {
|
||||
const fixture = initTest(NgModelForm);
|
||||
fixture.componentInstance.name = 'Nancy';
|
||||
|
|
|
@ -435,6 +435,8 @@ export declare class NgModel extends NgControl implements OnChanges, OnDestroy {
|
|||
validator: ValidatorFn;
|
||||
viewModel: any;
|
||||
constructor(parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<Validator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
|
||||
compositionEnd(): void;
|
||||
compositionStart(): void;
|
||||
ngOnChanges(changes: SimpleChanges): void;
|
||||
ngOnDestroy(): void;
|
||||
viewToModelUpdate(newValue: any): void;
|
||||
|
|
Loading…
Reference in New Issue