将表单传递给 AngularJS 组件进行验证
Posted
技术标签:
【中文标题】将表单传递给 AngularJS 组件进行验证【英文标题】:Passing form to AngularJS component for validation 【发布时间】:2016-08-27 03:14:57 【问题描述】:我正在将我的旧代码库迁移到使用 AngularJS 1.5 推广的新组件架构中。我在为较大的表单执行此操作时遇到了一个问题。传统上,我会按如下方式附加表单验证:
<form name="myForm">
<input type="text" name="input1" ng-model="vm.input1" required />
<div ng-messages="myForm.input1.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
<!-- many more inputs -->
</form>
当过渡到组件架构时,我必须明确地将表单传递给组件:
<form name="vm.myForm">
<my-awesome-input-component model="vm.input1" form="vm.myForm"><my-awesome-input-component>
<!-- many more inputs -->
</form>
我想避免用我的表单污染vm
。有没有更好的方法来实现表单所需的组件架构?
【问题讨论】:
您不需要污染您的视图模型,表单名称纯粹是表单控制器的名称,您可以将其传递给您的输入组件。您的视图模型应该只需要担心输入值。 【参考方案1】:实际上,您不需要传递表单父级来执行此操作。在你的 awesome-component 的模板中添加一个 ng-form 标签,然后使用它:
组件的模板:
<ng-form name="myComponentForm">
<input type="number" ng-model="$ctrl.myModel" name="myField"/>
<span ng-show="myComponentForm.myField.$invalid">There's an error</span>
</ng-form>
这就是ngForm指令的意思,指令和组件中有子表单对表单字段的子组进行验证。
【讨论】:
【参考方案2】:这是另一种可能对某些人有用的方法。使用require
将父form
包含在您的$ctrl
中:
angular.module("myApp")
.component("myInput",
templateUrl:'path/to/template.html'
bindings:
myInputModel:'<',
onUpdate:'&'
,
controller: MyInputController,
require:
form: '^form'
在输入模板中:
<input type="text" name="myInput" ng-model="$ctrl.myInputModel" ng-change="$ctrl.update($ctrl.myInputModel)" required />
<div ng-messages="$ctrl.form.myInput.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
无需将表单显式传递到您的组件中,因为form
会自动添加到您的$ctrl
:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input my-input-model="ctrl.anyModelIWant" on-update="ctrl.updateMyInput(value)"></my-input>
<button type="submit">Some button</button>
</form>
我猜从技术上讲,你仍然在污染你的虚拟机,但至少你不必在整个层次结构中明确地传递它。
添加文本以满足 6 个字符的编辑要求,将句点更改为逗号以更正示例。对于新人来说,时期是令人困惑的。
【讨论】:
【参考方案3】:更新 - 将 form-name 更改为 form-reference,因为我们传递实际的表单引用而不只是名称表格。这可以随心所欲地调用,只是要清楚它实际上是什么。
正如 Iain Reid 所说,您不需要为此使用 vm。您只需将表单命名为您想要的任何名称,然后将该名称传递给您的组件,因此它看起来像这样:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input form-reference="myForm"></my-input>
<button type="submit">Some button</button>
</form>
如果您想自己处理验证(我认为您可以使用 ng-messages),请确保您在表单中编写“novalidate”以禁用默认浏览器验证。
然后从那里,在我的组件上我会写如下内容:
angular.module("myApp")
.component("myInput",
templateUrl:'path/to/template.html'
bindings:
formReference:'<',
myInputModel:'<',
onUpdate:'&'
,
controller: MyInputController
然后在输入模板中:
<input type="text" name="myInput" ng-model="$ctrl.myInputModel" ng-change="$ctrl.update($ctrl.myInputModel)" required />
<div ng-messages="$ctrl.formReference.myInput.$error">
<div ng-message="required">Please fill out this field.</div>
</div>
关于绑定以及如何传递和更新模型的一些额外说明:
' :表示一种方式绑定,Angular 说它适用于所有人 组件从现在开始。为了更新值并有两种方式 绑定,我们需要包含一个“onUpdate”函数。 onUpdate : '&' 我在这里说的是我将通过一个 更新模型的函数(组件事件的回调)。所以在输入控制器中我会写如下内容:
function MyInputController()
var ctrl = this;
ctrl.update = function(value)
ctrl.onUpdate(value: value);
;
最后,当我在表单中使用我的组件时:
<form name="myForm" ng-submit="ctrl.someFunction()" novalidate>
<my-input form-reference="myForm" my-input-model="ctrl.anyModelIWant" on-update="ctrl.updateMyInput(value)"></my-input>
<button type="submit">Some button</button>
</form>
并且表单的控制器会有一个功能:
...
ctrl.updateMyInput = function(value)
ctrl.anyModelIWant = value;
...
官方文档:https://docs.angularjs.org/guide/component
我希望所有这些都能帮助到那里的人:-)
【讨论】:
很好的例子,但有一件事可能令人困惑——在你给出的例子中,你没有将表单名称(“myForm”)绑定到组件——你将实际引用绑定到表格。不过,它的效果很好,但一开始确实让我有些困惑。以上是关于将表单传递给 AngularJS 组件进行验证的主要内容,如果未能解决你的问题,请参考以下文章
将 AngularJS 数组传递给降级的 Angular 7 组件