ControlValueAccessor 是什麼?為什麼需要使用 ?下面本篇文章就來帶大家瞭解Angular中的ControlValueAccessor元件介面,希望對大家有所幫助!
簡單來說ControlValueAccessor是一個介面,它被用於在 Angular 的 FormControl 範例和原生 DOM 元素之間建立一個橋樑。其使用方式和OnInit類似,需要程式設計師在自定義元件裡面實現相應的方法。
import {
ControlValueAccessor,
NG_VALUE_ACCESSOR
} from '@angular/forms';
@Component({
selector: 'custom',
templateUrl: './custom.component.html',
styleUrls: ['./custom.component.less'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomComponent),
multi: true
}
]
})
export class CustomComponent implements ControlValueAccessor, OnInit, {…
登入後複製
有時,你可能需要建立自定義的表單元素,並希望它能和Angular的FormControl成功通訊。這時你便需要ControlValueAccessor來實現這個目的。
比如:
this.myForm = new FormGroup({
userName: new FormControl({value: '', disabled: false})
});
登入後複製
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label>
Name:
<my-input formControlName="userName"></my-input>
</label>
</div>
<div class="form-group">
<button type="submit">Submit</button>
</div>
</form>
登入後複製
ControlValueAccessor的使用方法在Angular官網和很多的文章中都有介紹,但是它具體是如何起作用的呢?
Angular 需要一種通用機制來橋接原生/自定義表單控制元件和 formControl 指令,而這正是 ControlValueAccessor 乾的事情。這個物件橋接原生表單控制元件和 formControl 指令,並同步兩者的值。任何一個元件或指令都可以通過實現 ControlValueAccessor 介面並註冊為 NG_VALUE_ACCESSOR,從而轉變成 ControlValueAccessor 型別的物件。
其實原生表單控制元件也擁有類似於ControlValueAccessor的介面,比如:當 Angular 在元件模板中中遇到 input 或 textarea DOM 原生控制元件時,就會使用DefaultValueAccessor 指令
Accessor | Form Element |
DefaultValueAccessor | input,textarea |
CheckboxControlValueAccessor | input[type=checkbox] |
NumberValueAccessor | input[type=number] |
RadioControlValueAccessor | input[type=radio] |
RangeValueAccessor | input[type=range] |
SelectControlValueAccessor | select |
SelectMultipleControlValueAccessor | select[multiple] |
以上是Angular 為所有原生 DOM 表單元素建立的 Angular 表單控制元件,即內建ControlValueAccessor
- writeValue(obj:any):將表單模型中的新值寫入檢視或DOM屬性(如果需要)的方法,它將來自外部的資料寫入到內部的資料模型。
- registerOnChange(fn:any):一種註冊處理程式的方法,當檢視中的某些內容發生更改時應呼叫該處理程式。它具有一個告訴其他表單指令和表單控制元件以更新其值的函數。通常在 registerOnChange 中需要儲存該事件觸發函數,在資料改變的時候,可以通過呼叫事件觸發函數通知外部資料變了,同時可以將修改後的資料作為引數傳遞出去。
- registerOnTouched(fn: any):註冊 onTouched 事件,基本同 registerOnChange ,只是該函數用於通知表單元件已經處於 touched 狀態,改變繫結的 FormControl 的內部狀態。
- setDisabledState(isDisabled: boolean):當呼叫 FormControl 變更狀態的 API 時得表單狀態變為 Disabled 時呼叫 setDisabledState() 方法,以通知自定義表單元件當前表單的讀寫狀態。
formControl 指令使用 writeValue 方法設定原生表單控制元件的值;使用 registerOnChange 方法來註冊由每次原生表單控制元件值更新時觸發的回撥函數,我們需要把更新的值傳給這個回撥函數,這樣對應的 Angular 表單控制元件值也會更新;使用 registerOnTouched 方法來註冊使用者和控制元件互動時觸發的回撥。
formControl會呼叫名為setUpControl的函數,ControlValueAccessor的範例valueAccessor會被作為引數傳入這個函數中。在setUpControl中,ControlValueAccessor的四個方法會在互動時被呼叫,以完成formControl和元素之間的通訊。
在使用ControlValueAccessor時需要一同引入NG_VALUE_ACCESSOR,它是使用InjectionToken 建立的可在 Provider 中使用的 Token。我們在編寫自己的專案時一般不需要用到InjectionToken,但是在一個框架或者第三方的外掛中,它就變得十分有必要了。
export const NG_VALUE_ACCESSOR =
new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');
登入後複製
試想當我使用依賴注入的功能時,我需要將我建立的依賴註冊進元件中。這時我就需要一個令牌,如果我使用一個字串作為令牌就有可能會造成重複,相同的令牌會導致後面的覆蓋前面的。所以需要一個Token作為一個唯一值來防止這種衝突。
providers: [{ provide: TOKEN, useValue: … }]
登入後複製
更多程式設計相關知識,請存取:!!
以上就是Angular學習之ControlValueAccessor介面詳解的詳細內容,更多請關注TW511.COM其它相關文章!