Angular 自定義表單控件 -- CheckboxGroupComponent


ControlValueAccessor

一般我們要實現一個自定義表單控件,首先要做的就是實現 ControlValueAccessor 接口。

ControlValueAccessor 是一個連接表單模型和視圖(DOM元素)的接口,自定義的表單控件必須實現這個接口,它的作用是:

  • 把 form 模型中值映射到視圖中
  • 當視圖發生變化時,通知 form directives 或 form controls

這個接口提供了以下方法:

interface ControlValueAccessor {
  writeValue(obj: any): void //數據由模型更新到視圖(model->view)時,方法被調用
  registerOnChange(fn: any): void //數據由視圖更新到模型(view->model)時,方法被調用
  registerOnTouched(fn: any): void
  setDisabledState(isDisabled: boolean)?: void
}

NG_VALUE_ACCESSOR

利用這一 Token 可將控件注冊成為可讓表單訪問到其值的控件,使用方法如下:

providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => CheckboxGroupComponent),
    multi: true
}]
Note:Token NG_VALIDATORS 可將控件注冊成為可讓表單訪問到其驗證狀態的控件。

自定義表單控件 CheckboxGroupComponent

1. 控件模板(基於Ionic)

<ion-grid>
  <ion-row>
    <label>{{ groupName }}</label>
    <ion-col *ngFor="let e of options">
      <section>
        <mat-checkbox [disabled]="disabled"
                      [checked]="this.model.length && this.model.indexOf(e.id) > -1"
                      [value]="e[value]"
                      (change)="setValue(e)">
          {{ e[display] }} 
        </mat-checkbox>
      </section>
    </ion-col>
  </ion-row>
</ion-grid>

2.組件類

export class CheckboxGroupComponent implements ControlValueAccessor {

  @Input() options: any = [] //checkbox數據數組 包含 id/value/display 三個屬性  
  @Input() disabled: boolean = false //控件可用性
  @Input() display: string //display是展示到界面的名稱
  @Input() value: string //value是提交到后台的數據
  @Input() groupName: string //checkboxgroup的標題

  model: any = [] //存放每個checked value 實時變化
  onChange = (_: any) => {}
  onTouched = () => {}

  constructor() {
  }

  setValue(obj){ //復選框的狀態改變時觸發
    let { id } = obj //解構賦值 這里也可以寫value
    let index = this.model.indexOf(id)
    if(index > -1){
      //model中若存在則移除
      this.model.splice(index, 1)
      //onChange方法將值的改變傳遞給外部 如果不調用這一方法表單控件中得不到任何數據
      //這個this.model也就是控件使用時與 ngModel 綁定的值
      this.onChange(this.model)
    }else{
      //不存在則添加
      this.model.push(id)
      this.onChange(this.model)
    }
    console.log(this.model)
  }

  writeValue(value: any){
    if(value && value.length){
      this.model = value
    }else {
      this.model = []
    }
  }

  registerOnChange(fn: any){
    this.onChange = fn
  }

  registerOnTouched(fn: any){
    this.onTouched = fn
  }
}

3. 注冊為表單控件

@Component({
  selector: 'checkbox-group',
  templateUrl: 'checkbox-group.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => CheckboxGroupComponent),
    multi: true
  }]
})

4. 控件使用

<checkbox-group [groupName]="'愛好:'" [options]="hobbies" [display]="'title'"
          [value]="'value'" [(ngModel)]="hobby" formControlName="hobby">
</checkbox-group>
<p>{{inform.get('hobby').value | json}}</p>
hobbies = [
  { id: 1, title: '電影', value: 'movie' },
  { id: 2, title: '音樂', value: 'song' },
  { id: 3, title: '登山', value: 'mountain' },
  { id: 4, title: '閱讀', value: 'read' },
  { id: 5, title: '游泳', value: 'swim' },
]

使用響應式表單,控件名為hobby,顯示效果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM