dynamicvalidation和与AngularJSforms的名称

我有这种forms: http : //jsfiddle.net/dfJeN/

正如你所看到的,input的名字值是静态设置的:

name="username" 

,表单validation工作正常(添加一些东西,并从input中删除所有文本,一个文本必须出现)。

然后我尝试dynamic设置名称值: http : //jsfiddle.net/jNWB8/

 name="{input.name}" 

然后我将这个应用到我的validation

 login.{{input.name}}.$error.required 

(这个模式将用于ng-repeat),但我的表单validation被打破。 它在我的浏览器中正确解释(如果我检查元素,我看到login.username。$ error.required)。

任何想法 ?

编辑:在控制台中logging范围后,它出现了

 {{input.name}} 

expression式不是插值的。 我的表单是{{input.name}}属性,但没有用户名。

更新:由于1.3.0-rc.3 name =“{{input.name}}”按预期工作。 请参阅#1404

你不能做你想要这样做的事情。

假设你想要做的是你需要dynamic地添加元素到一个表单,像ng重复,你需要使用嵌套的ng表单来validation这些单独的项目:

 <form name="outerForm"> <div ng-repeat="item in items"> <ng-form name="innerForm"> <input type="text" name="foo" ng-model="item.foo" /> <span ng-show="innerForm.foo.$error.required">required</span> </ng-form> </div> <input type="submit" ng-disabled="outerForm.$invalid" /> </form> 

不幸的是,这并不是Angular的一个很好的loggingfunction。

使用嵌套的ngForm允许您从HTML模板中访问特定的InputController。 但是,如果您希望从另一个控制器访问它,则无济于事。

例如

 <script> function OuterController($scope) { $scope.inputName = 'dynamicName'; $scope.doStuff = function() { console.log($scope.formName.dynamicName); // undefined console.log($scope.formName.staticName); // InputController } } </script> <div controller='OuterController'> <form name='myForm'> <input name='{{ inputName }}' /> <input name='staticName' /> </form> <a ng-click='doStuff()'>Click</a> </div> 

我使用这个指令来帮助解决问题:

 angular.module('test').directive('dynamicName', function($compile, $parse) { return { restrict: 'A', terminal: true, priority: 100000, link: function(scope, elem) { var name = $parse(elem.attr('dynamic-name'))(scope); // $interpolate() will support things like 'skill'+skill.id where parse will not elem.removeAttr('dynamic-name'); elem.attr('name', name); $compile(elem)(scope); } }; }); 

现在,只要使用“dynamic名称”属性而不是“名称”属性,就可以使用dynamic名称。

例如

 <script> function OuterController($scope) { $scope.inputName = 'dynamicName'; $scope.doStuff = function() { console.log($scope.formName.dynamicName); // InputController console.log($scope.formName.staticName); // InputController } } </script> <div controller='OuterController'> <form name='myForm'> <input dynamic-name='inputName' /> <input name='staticName' /> </form> <a ng-click='doStuff()'>Click</a> </div> 

根据对Github的讨论,这个问题应该在AngularJS 1.3中解决。

同时,这是@caitp和@Thinkscape创build的临时解决scheme:

 // Workaround for bug #1404 // https://github.com/angular/angular.js/issues/1404 // Source: http://plnkr.co/edit/hSMzWC?p=preview app.config(['$provide', function($provide) { $provide.decorator('ngModelDirective', function($delegate) { var ngModel = $delegate[0], controller = ngModel.controller; ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) { var $interpolate = $injector.get('$interpolate'); attrs.$set('name', $interpolate(attrs.name || '')(scope)); $injector.invoke(controller, this, { '$scope': scope, '$element': element, '$attrs': attrs }); }]; return $delegate; }); $provide.decorator('formDirective', function($delegate) { var form = $delegate[0], controller = form.controller; form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) { var $interpolate = $injector.get('$interpolate'); attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope)); $injector.invoke(controller, this, { '$scope': scope, '$element': element, '$attrs': attrs }); }]; return $delegate; }); }]); 

在JSFiddle上演示。

@EnISeeK很好的一个….但我知道它是更优雅,不太突兀的其他指令:

 .directive("dynamicName",[function(){ return { restrict:"A", require: ['ngModel', '^form'], link:function(scope,element,attrs,ctrls){ ctrls[0].$name = scope.$eval(attrs.dynamicName) || attrs.dynamicName; ctrls[1].$addControl(ctrls[0]); } }; }]) 

只比EnlSeek解决scheme稍微改进一点

 angular.module('test').directive('dynamicName', ["$parse", function($parse) { return { restrict: 'A', priority: 10000, controller : ["$scope", "$element", "$attrs", function($scope, $element, $attrs){ var name = $parse($attrs.dynamicName)($scope); delete($attrs['dynamicName']); $element.removeAttr('data-dynamic-name'); $element.removeAttr('dynamic-name'); $attrs.$set("name", name); }] }; }]); 

这是一个暴徒试验 。 这里是详细的解释

我扩展了@caitp和@Thinkscape解决scheme,允许dynamic创build嵌套的ng表单 ,如下所示:

 <div ng-controller="ctrl"> <ng-form name="form"> <input type="text" ng-model="static" name="static"/> <div ng-repeat="df in dynamicForms"> <ng-form name="form{{df.id}}"> <input type="text" ng-model="df.sub" name="sub"/> <div>Dirty: <span ng-bind="form{{df.id}}.$dirty"></span></div> </ng-form> </div> <div><button ng-click="consoleLog()">Console Log</button></div> <div>Dirty: <span ng-bind="form.$dirty"></span></div> </ng-form> </div> 

这是我在JSFiddle上的演示。

我用Ben Lesh的解决scheme,对我来说效果很好。 但是我遇到的一个问题是,当我使用ng-form添加一个内部表单时,如果我正在使用ng-submit指令,那么所有的表单状态,例如form.$valid, form.$error

所以如果我有这个例子:

 <form novalidate ng-submit="saveRecord()" name="outerForm"> <!--parts of the outer form--> <ng-form name="inner-form"> <input name="someInput"> </ng-form> <button type="submit">Submit</button> </form> 

而在我的控制器中:

 $scope.saveRecord = function() { outerForm.$valid // this is undefined } 

所以我不得不回到使用常规的点击事件来提交表单,在这种情况下,必须传递表单对象:

 <form novalidate name="outerForm"> <!--remove the ng-submit directive--> <!--parts of the outer form--> <ng-form name="inner-form"> <input name="someInput"> </ng-form> <button type="submit" ng-click="saveRecord(outerForm)">Submit</button> </form> 

而修改后的控制器方法:

 $scope.saveRecord = function(outerForm) { outerForm.$valid // this works } 

我不太确定这是为什么,但希望它可以帮助别人。

这个问题已经在Angular 1.3+中修复了这是你正在尝试做的正确的语法:

 login[input.name].$invalid