Search code examples
javascriptangularjsangularjs-directiveangularjs-scopeangularjs-ng-repeat

Dynamic form name attribute <input type="text" name="{{ variable-name }}" /> in Angularjs


How would someone use formName.inputName.$valid when the "inputName" was dynamically created?

  <form name="formName">
    <input ng-repeat="(variable) in variables"
           type="text" name="variable.name"
           ng-model="variable.name" required />
 </form>

The output of the HTML input attribute 'name' would be the string "variablename", which would applied to ALL repeated inputs.

If we tried this

<form name="formName">
  <input ng-repeat="(variable) in variables"
         type="text" name="{{ variable.name }}"
         ng-model="variable.name" required />
</form>

The output of the HTML input attribute 'name' would be the string"{{ variable.name }}", which would be applied to ALL repeated inputs.

In either of these two conditions, a name attribute for each of the repeated input elements would not be created dynamically; ALL inputs would share the same input name. Not much good if you wanted to call a specific input based on a specific name.

  • need to use dynamic name values
  • need to be able to call $scope.formName.dynamicName.$valid
  • need to be able to call $scope.formName.$valid
  • need dynamic name input fields to be added to nested form, or master form

Solution

  • Looks like Angular 1.3 fixed this (https://stackoverflow.com/a/32907176/3854385)

    This is now possible with 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>
    

    Demo

    In some cases an inner form is a good solution if you can just pass the information: (https://stackoverflow.com/posts/12044600/) To solve the 'dynamic name' problem you need to create an inner form (see ng-form):

    <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>
                <button ng-click="doSomething(urlForm.socialUrl.$valid)">Test</button>
          </ng-form>
      </div>
    

    The other alternative would be to write a custom directive for this.

    Here is the jsFiddle showing the usage of the ngForm: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/