validar validaciones validacion formularios formulario con campos angularjs

validaciones - Validación dinámica y nombre en un formulario con AngularJS



validar formulario angular 6 (8)

Amplío un poco la solución @caitp y @Thinkscape para permitir ng-forms anidadas creadas dinámicamente, como esta:

<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>

Aquí está mi demo en JSFiddle .

Tengo este formulario: http://jsfiddle.net/dfJeN/

Como puede ver, el valor del nombre para la entrada está establecido estáticamente:

name="username"

, la validación del formulario funciona bien (agregar algo y eliminar todo el texto de la entrada, debe aparecer un texto).

Luego trato de establecer dinámicamente el valor del nombre: http://jsfiddle.net/jNWB8/

name="{input.name}"

Luego aplico esto a mi validación

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

(este patrón se usará en una repetición ng) pero la validación de mi formulario está rota. Se interpreta correctamente en mi navegador (si inspecciono el elemento vi login.username. $ Error.required).

Alguna idea ?

EDITAR: después de registrar el alcance en la consola, parece que el

{{input.name}}

la expresión no es interpolar Mi formulario como un atributo {{input.name}} pero sin nombre de usuario.

ACTUALIZACIÓN: desde 1.3.0-rc.3 name = "{{input.name}}" funciona como se esperaba. Por favor mira #1404


Bonito por @EnISeeK ... pero lo hice para ser más elegante y menos molesto para otras 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]); } }; }])


El problema debería solucionarse en AngularJS 1.3, según esta discusión en #1404 .

Mientras tanto, aquí hay una solución temporal creada por @caitp y @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; }); }]);

Demostración en JSFiddle .


Este problema se ha solucionado en Angular 1.3+ Esta es la sintaxis correcta para lo que intenta hacer:

login[input.name].$invalid


No puedes hacer lo que intentas hacer de esa manera.

Asumiendo que lo que estás tratando de hacer es agregar dinámicamente elementos a un formulario, con algo así como una repetición ng, necesitas usar ng-form anidado para permitir la validación de esos ítems individuales:

<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>

Lamentablemente, simplemente no es una característica bien documentada de Angular.


Solo un poco de mejora sobre la solución 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); }] }; }]);

Aquí hay una prueba de Plunker . Aquí hay una explicación detallada


Usar ngForm anidado le permite acceder al InputController específico desde la plantilla HTML. Sin embargo, si desea acceder desde otro controlador, no ayuda.

p.ej

<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>

Uso esta directiva para ayudar a resolver el 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); } }; });

Ahora usa nombres dinámicos donde sea necesario solo el atributo ''nombre dinámico'' en lugar del atributo ''nombre''.

p.ej

<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>


Utilicé la solución de Ben Lesh y me funciona bien. Pero un problema al que me enfrenté fue que cuando agregué un formulario interno usando ng-form , todos los estados del formulario, por ejemplo, form.$valid, form.$error etc. quedaron sin definir si estaba usando la directiva ng-submit .

Entonces, si tuviera esto, por ejemplo:

<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>

Y en mi controlador:

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

Así que tuve que volver a utilizar un evento de clic normal para enviar el formulario, en cuyo caso es necesario pasar el objeto de formulario:

<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>

Y el método del controlador revisado:

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

No estoy muy seguro de por qué es esto, pero espero que ayude a alguien.