我使用Angular 2 ngModel绑定遇到了一个问题。 plnkr
如果我使用ngModel将值绑定到子组件,则不会在子组件的OnInit函数上填充该值。所以,如果我绑定一个属性调用“boundName”,我尝试在OnInit中访问它,它将为null。但是,如果我将父控件中的相同值绑定到不使用ngModel而是输入参数,则可以在OnInit函数中访问该值。
所以..如果我的父组件创建一个子组件,如
<my-boundcomp [(ngModel)]="name" [(inputName)] ="name" ></my-boundcomp>
我的子组件onInit函数是
public ngOnInit() {
console.log("Input Name :" + this.inputName);
console.log("Bound Name :" + this.boundName);
this._boundNameOnInit = this.boundName; // <--- Going to be null
this._inputNameOnInit = this.inputName; // <--- Going to be not null
}
我发现这种行为很奇怪,而且出乎意料。我不确定这是一个错误还是我没有正确使用FormsModule ngModel,但有趣的是我认为我应该分享。
这是完整的plnkr https://plnkr.co/edit/Im5oz7q1HhG5MgGTTZ1R?p=preview
这段代码
[(ngModel)]="name"
设置NgModel
中OnInit
的值不是BoundValueComponent
。当从BoundValueComponent.writeValue
调用NgModel
时,然后设置boundName
。
我很确定这是按照设计的。
我相信如果你依赖于使用ControlValueAccessor时通过writeValue设置的值,这是一个“问题”。由于boundName已设置且ngOnInit是最先触发的事件之一,因此writeValue尚未有机会运行。
我尝试在其他一些生命周期钩子(AfterViewInit,AfterContentInit)上添加它,现在还为时尚早。事实上,如果你将boundName默认为''或者你会注意到在AfterViewInit或AfterContentInit中,它实际上在调用writeValue之前被清除。
因此,我建议在writeValue方法中设置您的值。如果您只需要设置一次,则可以使用标志。请参阅下面的代码......
export class BoundValueComponent implements OnInit, ControlValueAccessor {
@Input() inputName: string;
boundName: string;
private _boundNameOnInit : string;
private _inputNameOnInit : string;
private initialized: boolean = false;
private onTouchedCallback: () => void = noop;
private onChangeCallback: (_: any) => void = noop;
constructor() {
}
public ngOnInit() {
console.log("Input Name :" + this.inputName);
console.log("Bound Name :" + this.boundName);
// this._boundNameOnInit = this.boundName; // <--- Going to be null
this._inputNameOnInit = this.inputName; // <--- Going to be not null
}
get value(): any {
return this.boundName;
};
/**
* Set accessor including call the onchange callback.
*/
set value(v: any) {
if (v !== this.boundName) {
this.boundName = v;
this.onChangeCallback(v);
}
}
/**
* From ControlValueAccessor interface.
*/
writeValue(value: any) {
this.boundName = value;
if (!this.initialized) {
this._boundNameOnInit = this.boundName;
this.initialized = true;
}
}
.......