自定义表单组件分为单值组件和多值组件.
单值组件:input/select/radio/textarea
多值组件:checkbox/tree组件
条件:
1.必须实现ControlValueAccessor接口
不同输入控件的数据更新方式不一样。
比如input是设置value值,而checkbox是设置checked属性。
因此不同类型的输入控件都有一个ControlValueAccessor来更新视图
export interface ControlValueAccessor{ writeVlaue(obj:any) :void; //model->view registerOnchange(fn:any) :void; //view->model registerOnTouched(fn:any):void; setDisabledState?( isDisabled:boolean):void }
//实现 writeValue(value:any){ if(value!=this.innerVal){ this.innerVal=value; } }
2.必须注册成为表单组件(使用providers属性)
注释:
1.provide:将组件注册到DI框架,让其成为一个可被表单访问的组件
2.useExisting:让组件暴露对应的validatate方法实现表单验证
3.multi:为true时表示这个token对应多个依赖项,可在多个表单里使用,互不影响
@Component({ selector:'nw-input', templateUrl:'./nw-input.component.html', styleUrls:'./nw-input.component.scss', providers:[ provide:NG_VALUE_ACCESSOR, useExisting:forwardRef(()=>nwInputComponent), multi:true ] })
具体实现:
1.如果是单值表单组件,使用FormControl
//nw-select.component.ts @Component({ selector:'nw-select', templateUrl:'./nw-select.component.html', styleUrls:'./nw-select.component.scss', providers:[ provide:NG_VALUE_ACCESSOR, useExisting:forwardRef(()=>NwSelectComponent), multi:true ] }) export class NwSelectComponent implements ControlValueAccessor{ selectFormControl:FormControl=new FormControl(); getControl(vfn:ValidatorFn[]):FormControl{ if(!this.selectFormControl){ this.selectFormControl=new FormControl('',vfn) } return this.selectFormControl } }
//xx.component.ts export class xxComponent implements OnInit { thatForm:formGroup; @ViewChild('xxComp') xxComp:NwSelectComponent; ngOnInit(){ xx:this.xxComp.getControl([Validator.required,Validators.minLength(5)]) //验证条件还是数组 } }
2.如果是多值表单组件,使用FormArray
//nw-checkbox.component.ts @Component({ selector:'nw-checkbox', templateUrl:'./nw-checkbox.component.html', styleUrls:'./nw-checkbox.component.scss', providers:[ provide:NG_VALUE_ACCESSOR, useExisting:forwardRef(()=>NwCheckboxGroupComponent), multi:true ] }) export class NwCheckboxGroupComponent implements ControlValueAccessor{ checkboxFormArray:FormArray=new FormArray([]); getControls(vfn:ValidatorFn):FormArray{ if(!this.checkboxkFormArray){ this.checkboxFormArray=new FormArray([],vfn); } } cleanControls(){ while(this.checkboxFormArray.controls.length!==0){ this.checkboxFormArray.removeAt(0) } pushControl(id:any){ this.checkboxFormArray.push(new FormControl(id)) } } }
//xx.component.ts export class xxComponent implements OnInit { thatForm:FormGroup; @ViewChild(xxComp) xxComp:NwCheckboxGroupComponent; ngOnInit(){ this.thatFom=this.formBuilder.group({ xx:this.xxComp.getControls(Valitators.required) //验证条件不再允许数组了 }) } }