angular 自定义组件使用ngModel

1、首先需要导入FormsModule

import { FormsModule }   from '@angular/forms';

并在NgModule的imports中引入 FormsModule

否则会报错:

Can’t bind to ‘ngModel’ since it isn’t a known property of

 

2、效果图,自定义一个带查询条件查询框,基于Amexio框架

 

3、component.html

<amexio-row>
    <amexio-column size="3">
        <amexio-label size="small-bold">{{label}}</amexio-label>
    </amexio-column>
    <amexio-column size="2">
        <mat-select placeholder="无" style="line-height: 40px;" #operator [(ngModel)]="operatorValue">
            <mat-option *ngFor="let op of operations" [value]="op.data">
                {{ op.label }}
            </mat-option>
        </mat-select>
    </amexio-column>
    <amexio-column size="7">
        <amexio-text-input [has-label]="false" name="name" [(ngModel)]="value"></amexio-text-input>
    </amexio-column>
</amexio-row>

4、component.ts

import { Component, OnInit, Input, forwardRef, ViewChild } from '@angular/core';
import { TEXT_OPERATION_GROUP, SELECT_OPERATION_GROUP } from './search-input-operation-group';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { MatSelect } from '@angular/material/select';
 
@Component({
  selector: 'app-search-input',
  templateUrl: './search-input.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => SearchInputComponent),
    multi: true
  }]
})
export class SearchInputComponent implements ControlValueAccessor {
  @ViewChild('operator') operator:MatSelect;

  @Input() name:string; // 条件名称
  @Input() label:string; // 条件label
  @Input() type:string; // 条件类型

  private _operatorValue:string = ''; // 操作符
  private _value:string = ''; // 第一个值
  private _value2:string = ''; // 第二个值

  operations:Array<{data:string, label:string}>; // 操作符列表

  onModelChange: Function = () => { };

  constructor() { 
      
  } 

  ngOnInit() { 
    if(this.type == 'text'){
        this.operations = TEXT_OPERATION_GROUP;
    }else if(this.type == 'select'){
        this.operations = SELECT_OPERATION_GROUP;
    }
  } 

  // 页面的值改变,调用改方法,并调用onModelChange传入改变后的值,实现值得回传
  set value(value:string){
    this._value = value;
    this.onModelChange({op:this._operatorValue, value:this._value, value2:this._value2});
  }
  get value(){
    return this._value;
  }

  // 页面的操作符值改变,调用该方法,并调用onModelChange传入改变后的值,实现值得回传
  set operatorValue(value:string){
    this._operatorValue = value;
    this.onModelChange({op:this._operatorValue, value:this._value, value2:this._value2});
  }
  get operatorValue(){
    return this._operatorValue;
  }

  // 赋值时调用
  writeValue(val: object): void {
    if (val) {
      this.operator.value = val['op'];
    }else{
      val = {};
    }
  }

  
  registerOnChange(fn: any): void {
    // 页面值改变时,调用该方法,传入新值实现回传
    this.onModelChange = fn;
  }

  registerOnTouched(fn: any): void {
  }
}

5、使用

<amexio-column [size]="6">
    <app-search-input [label]="'客户编码'" [type]="'select'" [(ngModel)]="searchCondition['counterparty_cd']" name="counterparty_cd"></app-search-input>
</amexio-column>

 

使用说明:

1、自定义标签实现ControlValueAccessor接口,并实现其方法

writeValue

registerOnChange

registerOnTouched

 

2、在Component中加入providers

providers: [{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => SearchInputComponent),
  multi: true
}]

 

3、writeValue,给自定义组件赋值时调用

registerOnChange 页面值改变后,调用该方法然后把值回传给model中。

发表评论