原文出處:https://www.cnblogs.com/keatkeat/p/5821974.html (Angular表單學習日誌,內容豐富,本文只截取一個點)
更新 : 2017-10-18
formControl 的監聽與廣播
兩種監聽方式
1. control.valueChanges.subscribe(v)
2. control.registerOnChange((value, emitViewToModelChange)
通常我們是想監聽來自 view 的更新, 當 accessor.publishMethod(v) 的時候, 上面第一種會被廣播, 第二種則收不到. 所以想監聽 view -> model 使用第一種
那麼如果我們要監聽來自 control.setValue 的話, model -> view or just model change, 我們使用第 2 種,
setValue 的options參數允許我們廣播時聲明要不要 讓第一種和第二種觸發
emitEvent = false 第一種不觸發
emitModelToViewChange = false 第 2 種不觸發
emitViewToModelChange = false 第 2 種觸發, 然後第二個參數是 就是 emitViewToModelChange
對了,雖然兩種叫 changes 但是值一樣也是會觸發的,如果不想重複值觸發的話,自己寫過濾唄.
總結:
在做 view accessor 時, 我們監聽 formControl model to view 所以使用 registerOnChange
// view accessor
this.viewValue = this.formControl.value; // first time
this.formControl.registerOnChange((v, isViewToModel) => { // model to view
console.log('should be false', isViewToModel);
this.viewValue = v;
});
然後通過 formControl view to model 更新
viewToModel(value: any) {
this.formControl.setValue(value, {
emitEvent: true,
emitModelToViewChange: false,
emitViewToModelChange: true
});
}
然後呢在外部,我們使用 valueChanges 監聽 view to model 的變化
this.formControl.valueChanges.subscribe(v => console.log('view to model', v)); // view to model
再然後呢, 使用 setValue model to view
modelToView(value: any) {
this.formControl.setValue(value, {
emitEvent: false,
emitModelToViewChange: true,
emitViewToModelChange: false
});
}
最關鍵的是在做 view accessor 時, 不要依賴 valueChanges 應該只使用 registerOnChange, 這好比你實現 angular ControlvalueAccessor 的時候,我們只依賴 writeValue 去修改 view.
對於 model to view 的時候是否允許 emitEvent 完全可以看你自己有沒有對其依賴,但 view accessor 肯定是不依賴的,所以即使 emitEvent false, model to view 依然把 view 處理的很好纔對。