考虑以下反应式设置:
让我们拥有实现SimpleInputComponent
接口的自定义ControlValueAccessor
。将其添加到由ngIf
指令包装的应用模板中,以便我们可以在SimpleInputComponent
表达式更改时重新调用ngIf
的生命周期。
由于SimpleInputComponent
是通过FormControl
指令绑定到formControlName
实例的,因此您可以通过调用FormControl.setValue
方法来更改其值。
我希望FormControl.setValue
恰好触发一次SimpleInputComponent.writeValue
。不幸的是,这是不正确的。
FormControl.setValue
调用SimpleInputComponent.writeValue
生命周期的次数是SimpleInputComponent
的次数。
现在要模拟问题,您至少需要两个组件:
SimpleInputComponent:
import { Component, forwardRef, Input } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControlName } from '@angular/forms';
@Component({
selector: 'simple-input-text',
template: `
<input [name]="formControlName" type="text"
[(ngModel)]="value"
(input)="onChange($event)"
(blur)="onBlur()" />
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SimpleInputComponent), multi: true }
]
})
export class SimpleInputComponent implements ControlValueAccessor {
private value: string;
constructor() { }
propagateChange: any = () => {};
propagateTouch: any = () => {};
onBlur() {
this.propagateTouch();
}
onChange(event) {
this.propagateChange(event.target.value);
}
writeValue(value: any): void {
console.log('writeValue() called');
this.value = value;
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: () => void): void {
this.propagateTouch = fn;
}
setDisabledState?(isDisabled: boolean): void {}
}
AppComponent:
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<div>
<button (click)="hidden = !hidden">{{hidden ? 'show' : 'hide'}}</button>
<button (click)="changeValue()">change value</button>
</div>
<div [formGroup] = "form" *ngIf="!hidden">
<simple-input-text formControlName="test"></simple-input-text>
</div>
`
})
export class AppComponent {
hidden = false;
form = new FormGroup({
test: new FormControl('')
});
changeValue(): void {
console.log('changeValue() called');
this.form.get('test').setValue('another value');
}
}
AppComponent
包含2个按钮:
SimpleInputComponent
的生命周期FormControl.setValue
方法来运行SimpleInputComponent
更新writeValue
模拟场景:
实时示例位于https://stackblitz.com/edit/angular-bgp3kg
所以问题是:我做错了吗?
答案 0 :(得分:0)
我看到此修复程序的PR仍处于打开状态。您可以在这里查看。 https://github.com/angular/angular/pull/29335。
表示要变通,您可以在SimpleInputComponent中定义ngOnDestroy,如下所示,
ngOnDestroy() {
if (this.ngControl) {
this.ngControl.reset();
this.ngControl.valueAccessor &&
(this.ngControl.valueAccessor.writeValue = () => {});
}
}