15

I am trying to validate some form fields which are given to me from a backend endpoint...

So basically the input elements are dynamically created inside a ng-repeat. Therefore, the input attributes are also dynamically added, such as the type, name, etc...

However because the name attribute is dynamically added, when I try to validate it, like this, for example:

myForm.elName.$valid

It doesn't return anything because at this point, it doesn't know what elName is.

I created a jsFiddle to demonstrate the problem: http://jsfiddle.net/peduarte/HB7LU/1889/

Any help or advice will be much appreciated!

FANX.

EDIT:
I've been referring to this AWESOME documentation: http://docs.angularjs.org/api/ng.directive:input.email

peduarte
  • 1,667
  • 3
  • 16
  • 24
  • Please, develop. Why do you regret every seconds of angularJS? – Ant Mar 20 '14 at 06:36
  • 1
    This is what you are looking for http://stackoverflow.com/questions/27071413/dynamic-form-name-attribute-input-type-text-name-variable-name-in – SoEzPz Nov 21 '14 at 22:56

1 Answers1

36

Try my custom directive:

myApp.directive("dynamicName",function($compile){
  return {
      restrict:"A",
      terminal:true,
      priority:1000,
      link:function(scope,element,attrs){
          element.attr('name', scope.$eval(attrs.dynamicName));
          element.removeAttr("dynamic-name");
          $compile(element)(scope);
      }
   };
});

Use it:

<input dynamic-name="field.name"
       type="{{ field.type }}"
       placeholder="{{ field.name }}"
       ng-model="field.value"
       required>

DEMO

Explanation of the problem:

By default, input elements using ngModelController (ng-model) call FormController.$addControl when they are linked to register itself and expose a property on the FormController with the name property of the input which is {{ field.name }} in this case. Therefore, even though the control is registered but you don't have exposed properties on FormController with named email, firstName, you only have {{ field.name }} referencing the last input item

Explanation of the solution:

In this solution, I created a custom directive to replace the {{ field.name }} with the correct name at runtime.

For more information why I have to use terminal:true, and priority:1000, check out this discussion: Add directives from directive in AngularJS

Community
  • 1
  • 1
Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • 1
    A isolated scope can be used instead of scope.$eval: `scope: { dynamicName: '=' }` in the directive configuration then simply `scope.dynamicName` inside `link`. – Hugo Wood May 06 '14 at 11:56
  • 1
    @Hugo Wood: I don't think we need isolate scope here. The purpose of this directive is to `modify the current element` based on `current scope`. Using current scope is more appropriate IMO. – Khanh TO May 06 '14 at 12:36
  • can I loop through error messages dynamically ? they are hardcoded in the demo – sisimh Sep 01 '15 at 21:00
  • @sisimh: yes, just use javascript bracket notation: `{{ myForm[formFields[0].name].$valid }}`: http://jsfiddle.net/3qu3tu6f/ – Khanh TO Sep 02 '15 at 03:14
  • thank you for ur reply @KhanhTO , actually i am thinking of returning the validation error from the directive it self , in that case how can I concat form name with the error fields like what u did except that i dont have "myForm" hardcoded – sisimh Sep 02 '15 at 08:37
  • @sisimh: I'm not sure I understand what you mean. In that case, you can also apply javascript bracket notation like: `MyCtrl[myForm]` – Khanh TO Sep 02 '15 at 09:07