自定義表單組件分為單值組件和多值組件.
單值組件: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) //驗證條件不再允許數組了 }) } }