热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【荐】深入Angular自定义表单控件

推荐文章MaximKoretskyi:NeveragainbeconfusedwhenimplementingControlValueAccessorinAngul

推荐文章

Maxim Koretskyi :
Never again be confused when implementing ControlValueAccessor in Angular forms


推荐理由

在大型复杂的管理后台项目中,很有可能你会遇到需要自定义表单控件(Custom form control)。很多文章都介绍了此时应该定义ControlValueAccessor,也展示了如何实现,但并没有说出为什么,这个类在Angular的表单架构中起了什么作用。该文章就解决了为什么的问题,让你从原理理解自定义表单控件。


文章概要

首先,只要你创建表单,Angular就会创建对应FormControl,无论是模板驱动表单还是响应式表单。模板驱动表单的FormControl是由NgModel指令隐性创建,而响应式表单是由你自己创建,通过FormControlName指令将Angular表单元素和原生表单元素进行绑定。

// packages/forms/src/directives/ng_model.ts
@Directive({selector: '[ngModel]...',...
})
export class NgModel ... {_control &#61; new FormControl(); <---------------- 这里

也就是说在Angular中的表单&#xff0c;不是原生表单&#xff0c;而是封装后的Angular表单。不仅仅是原生的表单控件可以处理封装成Angular表单&#xff0c;其他自定义的Angular组件也可以&#xff0c;只要定义了ControlValueAccessor

ControlValueAccessor是什么呢&#xff1f;它是原生元素和Angular表单之间的桥梁&#xff0c;将组件或者指令继承ControlValueAccessor的接口就能变成Angular表单使用了。

ControlValueAccessor接口长这样&#xff1a;

// packages/forms/src/directives/control_value_accessor.ts
interface ControlValueAccessor {writeValue(obj: any): voidregisterOnChange(fn: any): voidregisterOnTouched(fn: any): void...
}

writeValue是在初始化的时候将formControl的值传递给原生表单控件&#xff1b;registerOnChange用来获取原生表单控件的值更新时通知Angular表单控件更新的函数&#xff1b;registerOnTouched用来获取通知用户正在交互的函数。

image

明确来说&#xff0c;那些原生表单控件都有其对应的ControlValueAccessor&#xff1a;

&#43;------------------------------------&#43;----------------------&#43;
| Accessor | Form Element |
&#43;------------------------------------&#43;----------------------&#43;
| DefaultValueAccessor | input, textarea |
| CheckboxControlValueAccessor | input[type&#61;checkbox] |
| NumberValueAccessor | input[type&#61;number] |
| RadioControlValueAccessor | input[type&#61;radio] |
| RangeValueAccessor | input[type&#61;range] |
| SelectControlValueAccessor | select |
| SelectMultipleControlValueAccessor | select[multiple] |

那原生表单控件和Angular表单控件保持一致的原理是什么呢&#xff1f;

我们看下formControl指令的实现&#xff1a;

// packages/forms/src/directives/reactive_directives/form_control_directive.tsexport class FormControlDirective ... {...ngOnChanges(changes: SimpleChanges): void {if (this._isControlChanged(changes)) {setUpControl(this.form, this);

formControl指令调用了setUpControl函数来实现formControlControlValueAccessor之间的交互。

// packages/forms/src/directives/shared.tsexport function setUpControl(control: FormControl, dir: NgControl) {// 初始化原生表单控件dir.valueAccessor.writeValue(control.value);// 监听原生表单控件&#xff0c;将值同步给form controldir.valueAccessor.registerOnChange((newValue: any) &#61;> {...control.setValue(newValue, {emitModelToViewChange: false});});// 反之&#xff0c;监听form control&#xff0c;将值同步给原生表单控件control.registerOnChange((newValue: any, ...) &#61;> {dir.valueAccessor.writeValue(newValue);});

到此&#xff0c;我们应该明白ControlValueAccessor中定义writeValue等函数是怎么work了吧。

以上就是最重要的原理部分。

接下来&#xff0c;作者通过第三方组件jquery-slider来演示了如何用Angular封装第三方组件库&#xff0c;以及如何将该组件封装成自定义表单控件。具体教程可以看原文。


延伸阅读


  • semlinker: Angular 4.x 自定义表单控件

本文首发知乎野草。如有不当之处&#xff0c;欢迎指正。


推荐阅读
author-avatar
mobiledu2502881303
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有