Eu tenho este formulário: http://jsfiddle.net/dfJeN/
Como você pode ver, o valor do nome da input é definido estaticamente:
name="username"
, a validação de formulário funciona bem (adicione algo e remova todo o texto da input, um texto deve aparecer).
Então eu tento definir dinamicamente o valor do nome: http://jsfiddle.net/jNWB8/
name="{input.name}"
Então eu aplico isso à minha validação
login.{{input.name}}.$error.required
(esse padrão será usado em um ng-repeat), mas a validação do meu formulário está quebrada. É interpretado corretamente no meu navegador (se eu inspecionar o elemento, eu vi login.username. $ Error.required).
Qualquer ideia ?
EDIT: Depois de registrar o escopo no console, parece que o
{{input.name}}
a expressão não é interpolada. Minha forma como um atributo {{input.name}}, mas sem nome de usuário.
UPDATE: Desde 1.3.0-rc.3 name = “{{input.name}}” funciona como esperado. Por favor, veja # 1404
Você não pode fazer o que está tentando fazer dessa maneira.
Supondo o que você está tentando fazer é que você precisa adicionar dinamicamente elementos a um formulário, com algo como um ng-repeat, você precisa usar o ng-form nested para permitir a validação desses itens individuais:
Infelizmente, não é apenas uma característica bem documentada do Angular.
O uso do ngForm nested permite acessar o InputController específico a partir do modelo HTML. No entanto, se você deseja acessá-lo de outro controlador, isso não ajuda.
por exemplo
Eu uso essa diretiva para ajudar a resolver o problema:
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); } }; });
Agora você usa nomes dynamics onde é necessário apenas o atributo ‘dynamic-name’ em vez do atributo ‘name’.
por exemplo
O problema deve ser corrigido no AngularJS 1.3, de acordo com essa discussão no Github .
Enquanto isso, aqui está uma solução temporária criada por @caitp e @Thinkscape :
// 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; }); }]);
Demonstração no JSFiddle .
Nice por @EnISeeK …. mas eu tenho que ser mais elegante e menos intrusivo a outras directivas:
.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]); } }; }])
Apenas um pouco de melhoria sobre a solução da EnlSeek
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); }] }; }]);
Aqui está um julgamento plunker . Aqui está uma explicação detalhada
Eu amplio um pouco a solução @caitp e @Thinkscape, para permitir que ng-forms nesteds criados dinamicamente, assim:
Dirty: Dirty:
Aqui está minha demonstração no JSFiddle .
Eu usei a solução de Ben Lesh e funciona bem para mim. Mas um problema que enfrentei foi que quando adicionei uma forma interna usando ng-form
, todos os estados de formulário, por exemplo, form.$valid, form.$error
etc ficaram indefinidos se eu estivesse usando a diretiva ng-submit
.
Então, se eu tivesse isso, por exemplo:
E no meu controlador:
$scope.saveRecord = function() { outerForm.$valid // this is undefined }
Então, tive que voltar a usar um evento de clique regular para enviar o formulário. Nesse caso, é necessário passar o object de formulário:
E o método revisado do controlador:
$scope.saveRecord = function(outerForm) { outerForm.$valid // this works }
Eu não tenho certeza porque isso é, mas espero que ajude alguém.
Este problema foi corrigido no Angular 1.3+ Esta é a syntax correta para o que você está tentando fazer:
login[input.name].$invalid