zoukankan      html  css  js  c++  java
  • 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,显示效果如下:

  • 相关阅读:
    H5+ 分享到微信、朋友圈代码示例
    H5+ 重写在线升级版本比较代码
    H5+ a页面打开b页面,b页面加载成功后关闭当前页面,闪屏的规避解决方案
    MUI
    MUI
    MUI
    MUI
    Vue实战之【企业开发常见问题】
    step1:准备歌词之《前端开发是个啥》
    element-ui级联选择器(Cascader)获取级联对象 (主要是想获取:label值)
  • 原文地址:https://www.cnblogs.com/qimeng/p/9509955.html
Copyright © 2011-2022 走看看