如何创建自定义组件,就像本机 <input>
标签一样?我想让我的自定义表单控件能够支持ngControl,ngForm,[(ngModel)] .
据我所知,我需要实现一些接口,使我自己的表单控件工作就像本机一样 .
此外,似乎ngForm指令仅绑定 <input>
标签,这是对的吗?我该如何处理?
让我解释为什么我需要这个 . 我想包装几个输入元素,使它们能够作为一个单独的输入一起工作 . 还有其他方法可以解决这个问题吗?还有一次:我想让这个控件像原生控件一样 . 验证,ngForm,ngModel双向绑定等 .
ps:我使用的是Typescript .
7 回答
实际上,有两件事要实现:
提供表单组件逻辑的组件 . 它不是输入,因为它将由
ngModel
本身提供自定义
ControlValueAccessor
将实现此组件与ngModel
/ngControl
之间的桥梁我们来试试吧 . 我想实现一个管理公司标签列表的组件 . 该组件将允许添加和删除标签 . 我想添加一个验证,以确保标签列表不为空 . 我将在我的组件中定义它,如下所述:
TagsComponent
组件定义了添加和删除tags
列表中元素的逻辑 .如您所见,此组件中没有输入,但是
setValue
(此处名称并不重要) . 我们稍后使用它来提供ngModel
到组件的值 . 此组件定义在更新组件状态(标记列表)时要通知的事件 .现在让我们实现这个组件和
ngModel
/ngControl
之间的链接 . 这对应于实现ControlValueAccessor
接口的指令 . 必须针对NG_VALUE_ACCESSOR
令牌为此值访问器定义提供程序(不要忘记使用forwardRef
,因为后面定义了该指令) .该指令将在主机的
tagsChange
事件上附加一个事件监听器(即指令附加的组件,即TagsComponent
) . 事件发生时将调用onChange
方法 . 此方法对应于Angular2注册的方法 . 这样,它将意识到相应的表单控件的更改和更新 .更新
ngForm
中的值时将调用writeValue
. 在注入附加的组件(即TagsComponent)之后,我们将能够调用它来传递该值(参见前面的setValue
方法) .不要忘记在指令的绑定中提供
CUSTOM_VALUE_ACCESSOR
.以下是自定义
ControlValueAccessor
的完整代码:这样,当我删除公司的所有
tags
时,companyForm.controls.tags
控件的valid
属性自动变为false
.有关更多详细信息,请参阅此文章(“与NgModel兼容的组件”一节):
使用
ControlValueAccessor
NG_VALUE_ACCESSOR
非常容易 .您可以阅读这篇文章来制作一个简单的自定义字段Create Custom Input Field Component with Angular
蒂埃里的例子很有帮助 . 以下是TagsValueAccessor运行所需的导入...
您也可以使用@ViewChild指令解决此问题 . 这使父级可以完全访问注入子级的所有成员变量和函数 .
见:How to access input fields of injected form component
我不明白为什么我在互联网上找到的每个例子都必须如此复杂 . 在解释一个新概念时,我认为最简单的工作示例总是最好的 . 我把它蒸馏了一下:
使用实现ngModel的组件的外部表单的HTML:
自包含的组件(没有单独的'访问者'类 - 也许我错过了这一点):
事实上,我刚刚将所有这些内容抽象为一个抽象类,我现在使用ngModel扩展每个组件 . 对我来说,这是一大笔开销和样板代码,我可以不用 .
编辑:这是:
这是一个使用它的组件:(TS):
HTML:
RC5版本链接中有一个示例:http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel
然后我们可以使用此自定义控件,如下所示:
为什么要在使用内部ngModel时创建新的值访问器 . 每当您创建一个包含输入[ngModel]的自定义组件时,我们就已经在实例化一个ControlValueAccessor . 这就是我们需要的访问者 .
模板:
零件:
用于: