Angular封装表单控件及思想总结
前言
前端框架的强大无疑给开发者省去了不少烦恼,又因比较完善的UI库支撑,让部分后端开发者能够省去大量样式设计的时间成本,纵然如此,业务的多变性是框架本身无法预料的,很多的控件功能在实际开发中总是不够完善和灵活,所以需要开发者结合业务需求进行再次封装这些UI控件/组件。
表单控件
常规组件只需要根据官方指引,写好数据传输的方式和订阅即可任意使用,表单控件有点特殊,按照常规方式写出来的组件使用在表单中,绑定ngModel或者formControlName,随之而来的是一个报错:
RRORError:Novalueaccessorforformcontrolwithname:'userName'
ControlValueAccessor
DefinesaninterfacethatactsasabridgebetweentheAngularformsAPIandanativeelementintheDOM
只有实现了这个接口才可以完成像普通表单元素那样使用和验证。
interfaceControlValueAccessor{
writeValue(obj:any):void
registerOnChange(fn:any):void
registerOnTouched(fn:any):void
setDisabledState(isDisabled:boolean)?:void
}
你的控件必须包含上述方法;此外,控件内部要有value的get实现,以及最好有个与value等值的别名变量(想不明白别急,看代码);一个简单的input控件封装应该类似这样:
exportclassMyInputComponentimplementsOnInit,ControlValueAccessor{
value:string|number;
@Input()disabled:boolean;
@Input()placeholder:string;
@Input()type='text';
constructor(){}
ngOnInit(){
}
writeValue(data:any){
this.value=data;
}
registerOnChange(fn:any){
}
registerOnTouched(fn:any){
}
setDisabledState(disabled:boolean){
this.disabled=disabled;
}
}
其实封装工作只完成一半,组件装饰器元数据完整:
@Component({
//tslint:disable-next-line:component-selector
selector:'my-input',
templateUrl:'./my-input.component.html',
styleUrls:['./my-input.component.scss'],
providers:[{
provide:NG_VALUE_ACCESSOR,
useExisting:forwardRef(()=>MyInputComponent),
multi:true
}]
})
至此,控件在form表单中使用不会报错;表单内放置一个查询按钮,用来输出表单状态:
userName
ngOnInit(){
this.form=this.fb.group({
userName:[2]
});
}
submit(form:FormGroup){
console.log(form);
}
封装控件内部: