我有一个使用ng-repeat创建的表。我想向表中的每个元素添加验证。问题是每个输入单元格与它上面和下面的单元格具有相同的名称。我尝试使用HTML值来命名输入,但是尽管{{$index}}
中的字符串文字看起来是正确的,它现在仍然可以工作。
这是我现在的代码:
<tr ng-repeat="r in model.BSM ">
<td>
<input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
</td>
</tr>
我曾尝试从索引中删除{{}}
,但也不起作用。到目前为止,输入的validation属性工作正常,但没有显示错误消息。
有人有什么建议吗?
编辑:除了下面的精彩答案之外,还有一篇博客文章更详细地介绍了这个问题:http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2/
发布于 2012-08-21 04:24:30
AngularJS依赖输入名称来暴露验证错误。
不幸的是,到目前为止,还不可能(不使用自定义指令)动态生成输入的名称。实际上,检查input docs,我们可以看到name属性只接受一个字符串。
要解决“动态名称”问题,您需要创建一个内部表单(请参见 )
<div ng-repeat="social in formData.socials">
<ng-form name="urlForm">
<input type="url" name="socialUrl" ng-model="social.url">
<span class="alert error" ng-show="urlForm.socialUrl.$error.url">URL error</span>
</ng-form>
</div>
另一种选择是为此编写一个自定义指令。
下面的jsFiddle显示了ngForm的用法:http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/
发布于 2015-10-02 20:27:46
因为这个问题被问到了,Angular团队已经解决了这个问题,它使得动态创建输入名称成为可能。
使用Angular 1.3和更高版本的,您现在可以这样做:
<form name="vm.myForm" novalidate>
<div ng-repeat="p in vm.persons">
<input type="text" name="person_{{$index}}" ng-model="p" required>
<span ng-show="vm.myForm['person_' + $index].$invalid">Enter a name</span>
</div>
</form>
Angular 1.3还引入了ngMessages,一个更强大的表单验证工具。您可以对ngMessages使用相同的技术:
<form name="vm.myFormNgMsg" novalidate>
<div ng-repeat="p in vm.persons">
<input type="text" name="person_{{$index}}" ng-model="p" required>
<span ng-messages="vm.myFormNgMsg['person_' + $index].$error">
<span ng-message="required">Enter a name</span>
</span>
</div>
</form>
发布于 2014-06-29 04:00:53
如果不想使用ng-form,可以使用定制指令来更改表单的name属性。将此指令作为属性放在与ng-model相同的元素上。
如果您同时使用其他指令,请注意它们没有设置"terminal“属性,否则此函数将无法运行(假设它的优先级为-1)。
例如,将此指令与ng-options一起使用时,必须运行一行monkeypatch:https://github.com/AlJohri/bower-angular/commit/eb17a967b7973eb7fc1124b024aa8b3ca540a155
angular.module('app').directive('fieldNameHack', function() {
return {
restrict: 'A',
priority: -1,
require: ['ngModel'],
// the ngModelDirective has a priority of 0.
// priority is run in reverse order for postLink functions.
link: function (scope, iElement, iAttrs, ctrls) {
var name = iElement[0].name;
name = name.replace(/\{\{\$index\}\}/g, scope.$index);
var modelCtrl = ctrls[0];
modelCtrl.$name = name;
}
};
});
我经常发现使用ng-init将$index设置为变量名很有用。例如:
<fieldset class='inputs' ng-repeat="question questions" ng-init="qIndex = $index">
这会将正则表达式更改为:
name = name.replace(/\{\{qIndex\}\}/g, scope.qIndex);
如果您有多个嵌套的ng-repeats,您现在可以使用这些变量名来代替$parent.$index。
指令的“终端”和“优先级”的定义:https://docs.angularjs.org/api/ng/service/$compile#directive-definition-object
Github关于ng-option monkeypatch需求的评论:https://github.com/angular/angular.js/commit/9ee2cdff44e7d496774b340de816344126c457b3#commitcomment-6832095 https://twitter.com/aljohri/status/482963541520314369
更新:
您也可以使用ng-form来实现这一点。
angular.module('app').directive('formNameHack', function() {
return {
restrict: 'A',
priority: 0,
require: ['form'],
compile: function() {
return {
pre: function(scope, iElement, iAttrs, ctrls) {
var parentForm = $(iElement).parent().controller('form');
if (parentForm) {
var formCtrl = ctrls[0];
delete parentForm[formCtrl.$name];
formCtrl.$name = formCtrl.$name.replace(/\{\{\$index\}\}/g, scope.$index);
parentForm[formCtrl.$name] = formCtrl;
}
}
}
}
};
});
https://stackoverflow.com/questions/12044277
复制相似问题