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); }
封装控件内部: