ControlValueAccessor (CVA)
[Angular] Forms - Control Value Accessor [上] - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
[Angular] Day28. Control Value Accessor (CVA) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
ControlValueAccessor (CVA) 是什麼?
ControlValueAccessor 是 Angular 中的一個介面,它作為 Angular 表單系統 (FormControl, FormGroup 等) 和 DOM 元素之間的橋樑。簡單來說,它負責:
將表單控制項的值寫入到 DOM 元素
從 DOM 元素讀取使用者輸入的值到表單控制項
處理表單控制項的禁用狀態
為什麼需要實作 ControlValueAccessor?
當你建立自定義表單控制項(如 app-multiple-select)並想要它與 Angular 的表單系統整合時,你需要告訴 Angular 如何:
將值從表單模型寫入你的元件
將使用者在你的元件中的操作轉換回表單模型的值
處理禁用狀態等
[formControl] vs formControlName 的差異
當你使用 [formControl]="someControl"
時,你可以不需要實作 ControlValueAccessor,為什麼?
[formControl]="someControl":這是直接將一個 FormControl 實例傳遞給元件,是使用屬性綁定的方式。在這種情況下,你的元件可以直接讀取和操作這個 FormControl 實例,不需要通過 ControlValueAccessor 介面。
formControlName="controlName":這是在使用 FormGroup 和 formGroupName 的情境下,你只提供控制項的名稱,而不是控制項本身。在這種情況下,Angular 需要知道如何將表單系統中的值與你的元件連接起來,因此需要 ControlValueAccessor 來做這個轉換。
為什麼普通的 formControl 不需要 CVA?
當你使用 [formControl]
綁定時,你可以直接在元件中訂閱和更新這個控制項:
@Input() formControl: FormControl;
ngOnInit() {
// 直接訂閱控制項的值變化
this.formControl.valueChanges.subscribe(newValue => {
// 處理值變化
});
}
onChange(newValue) {
// 直接更新控制項的值
this.formControl.setValue(newValue);
}
這樣你可以直接操作 FormControl 實例,不需要中間層的 ControlValueAccessor。
但是,當你使用 formControlName
時,你的元件需要實作 ControlValueAccessor 介面,讓 Angular 的表單模組知道如何與你的自定義元件互動:
// 需要實作 ControlValueAccessor 的四個核心方法
writeValue(value: any): void { /* 寫入值到 UI */ }
registerOnChange(fn: any): void { /* 註冊值變化時的回調 */ }
registerOnTouched(fn: any): void { /* 註冊被觸碰時的回調 */ }
setDisabledState(isDisabled: boolean): void { /* 設置禁用狀態 */ }
總結
如果你想讓元件支援
formControlName
指令,就必須實作 ControlValueAccessor 介面如果你只是想通過
[formControl]
傳遞控制項實例,則無需實作 ControlValueAccessorControlValueAccessor 允許你的自定義表單控制項無縫整合到 Angular 的表單系統中
Last updated