首頁 > web前端 > js教程 > 主體

詳解Angular使用ControlValueAccessor實作自訂表單控制項

青灯夜游
發布: 2021-04-28 09:34:59
轉載
2667 人瀏覽過

本篇文章跟大家介紹一下Angular使用ControlValueAccessor實作自訂表單控制項的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

詳解Angular使用ControlValueAccessor實作自訂表單控制項

Angular: [ControlValueAccessor] 自訂表單控制項


我們在實際開發中,通常會遇到各種各樣的客製化功能,會遇到有些元件會與Angular 的表單進行交互,這時候我們一般會從外部傳入一個FormGroup 對象,然後在元件的內部寫相應的邏輯對Angular 表單進行操作。如果我們只是對表單中的一個項目進行定制,將整個表單物件傳入顯然不合適,並且組件也會顯得臃腫。

<form [formGroup]="simpleForm">                                <br/>  <other-component [form]="simpleForm"></other-component>        <br/></form><br/>
登入後複製

那麼,我們能不能像原生表單一樣去使用這些自訂元件呢?目前,開源元件 ng-zorro-antd 表單元件能和原生表單一樣使用 formControlName 這個屬性,這類元件就叫自訂表單元件。 【相關推薦:《angular教學》】

如何實作自訂表單控制項

在Angular 中,使用ControlValueAccessor 可以實現元件與外層包裹的form 關聯起來。

ControlValueAccessor是用於處理以下內容的介面:

  • 將表單模型中的值寫入檢視/ DOM
  • 在檢視/ DOM變更時通知其他表單指令與控制項

ControlValueAccessor

ControlValueAccessor 介面定義了四種方法:

writeValue(obj: any): void<br/><br/>registerOnChange(fn: any): void<br/><br/>registerOnTouched(fn: any): void<br/><br/>setDisabledState(isDisabled: boolean)?: void<br/>
登入後複製

writeValue(obj:any) :將表單模型中的新值寫入視圖或DOM屬性(如果需要)的方法,它將來自外部的資料寫入到內部的資料模型。資料流向: form model -> component。

registerOnChange(fn:any):一種註冊處理程序的方法,當視圖中的某些內容發生變更時應呼叫該處理程序。它具有一個告訴其他表單指令和表單控制項以更新其值的函數。通常在 registerOnChange 中需要保存該事件觸發函數,在資料改變的時候,可以透過呼叫事件觸發函數通知外部資料變了,同時可以將修改後的資料作為參數傳遞出去。資料流向: component -> form model。

registerOnTouched(fn: any):註冊 onTouched 事件,基本上同 registerOnChange ,只是函數用來通知表單元件已經處於 touched 狀態,改變綁定的 FormControl 的內部狀態。狀態變更: component -> form model。

setDisabledState(isDisabled: boolean):當呼叫FormControl 變更狀態的API 時得表單狀態變為Disabled 時呼叫setDisabledState() 方法,以通知自訂表單元件目前表單的讀取寫狀態。狀態變更: form model -> component。

如何使用ControlValueAccessor

#建置控制項框架

@Component({<br/>  selector: &#39;app-test-control-value-accessor&#39;,<br/>  templateUrl: &#39;./test-control-value-accessor.component.html&#39;,<br/>  providers: [{<br/>    provide: NG_VALUE_ACCESSOR,<br/>    useExisting: forwardRef(() => TestControlValueAccessorComponent),<br/>    multi: true<br/>  }]<br/>})<br/>export class TestControlValueAccessorComponent implements ControlValueAccessor {<br/><br/>  _counterValue = 0;<br/> <br/>  private onChange = (_: any) => {};<br/><br/>  constructor() { }<br/><br/>  get counterValue() {<br/>    return this._counterValue;<br/>  }<br/><br/>  set counterValue(value) {<br/>    this._counterValue = value;<br/>    // 触发 onChange,component 内部的值同步到 form model<br/>    this.onChange(this._counterValue);<br/>  }<br/><br/>  increment() {<br/>    this.counterValue++;<br/>  }<br/><br/>  decrement() {<br/>    this.counterValue--;<br/>  }<br/><br/>  // form model 的值同步到 component 内部<br/>  writeValue(obj: any): void {<br/>    if (obj !== undefined) {<br/>      this.counterValue = obj;<br/>    }<br/>  }<br/><br/>  registerOnChange(fn: any): void {<br/>    this.onChange = fn;<br/>  }<br/><br/>  registerOnTouched(fn: any): void { }<br/><br/>  setDisabledState?(isDisabled: boolean): void { }<br/><br/>}<br/>
登入後複製

註冊ControlValueAccessor

為了獲得ControlValueAccessor 用於表單控件,Angular 內部將注入在NG_VALUE_ACCESSOR 令牌上註冊的所有值,這是將控製本身註冊到DI 框架成為一個可以讓表單存取其值的控制項。因此,我們需要做的就是NG_VALUE_ACCESSOR 使用我們自己的值存取器實例(這是我們的元件)來擴充 multi-provider 。所以設定 multi: true,是宣告這個 token 對應的類別很多,分散在各處。

這裡我們必須使用 useExisting,因為TestControlValueAccessorComponent 可能在使用它的元件中被其建立為指令依賴項。這就得用到 forwardRef 了,這個函數允許我們引用一個尚未定義的物件。

@Component({<br/>  ...<br/>  providers: [<br/>    { <br/>      provide: NG_VALUE_ACCESSOR,<br/>      useExisting: forwardRef(() => TestControlValueAccessorComponent ),<br/>      multi: true<br/>    }<br/>  ]<br/>})<br/>export class TestControlValueAccessorComponent implements ControlValueAccessor {<br/>  ...<br/>}<br/>
登入後複製

控制項介面

  • test-control-value-accessor.component.html
#
<div class="panel panel-primary"><br/>  <div class="panel-heading">自定义控件</div><br/>  <div class="panel-body"><br/>    <button (click)="increment()">+</button><br/>    {{counterValue}}<br/>    <button (click)="decrement()">-</button><br/>  </div><br/></div><br/>
登入後複製

#在表單中使用

  • app.component.html
<div class="constainer"><br/>  <form #form="ngForm"><br/>    <app-test-control-value-accessor name="message" [(ngModel)]="message"></app-test-control-value-accessor><br/>    <button type="button" (click)="submit(form.value)">Submit</button><br/>  </form><br/>  <pre class="brush:php;toolbar:false">{{ message }}


登入後複製
  • app.component.ts
@Component({<br/>  selector: &#39;app-root&#39;,<br/>  templateUrl: &#39;./app.component.html&#39;,<br/>  styleUrls: [&#39;./app.component.css&#39;]<br/>})<br/>export class AppComponent {<br/><br/>  message = 5;<br/><br/>  submit(value: any): void {<br/>    console.log(value);<br/>  }<br/><br/>}<br/>
登入後複製

#參考

  • https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular- 2.html

  • https://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

  • ## https://juejin.im/post/597176886fb9a06ba4746d15

  • https://github.com/shhdgit/blogs/issues/11

更多程式相關知識,請造訪:程式設計影片! !

以上是詳解Angular使用ControlValueAccessor實作自訂表單控制項的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:csdn.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!