Home » Angularjs » Dynamic form name attribute <input type=“text” name=“{{ variable-name }}” /> in Angularjs

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

Posted by: admin November 30, 2017 Leave a comment


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

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

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

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>


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>

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/


I could not find the answer that satisfied some or all of these needs. This is what I came up with.

There may be a better way, so please share your thoughts.
I am using Angularjs 1.3.0-beta.8

I have a form with multi-nested directives that all contain input(s), select(s), etc…
These elements are all enclosed in ng-repeats, and dynamic string values.

This is how to use the directive:

<form name="myFormName">
  <nested directives of many levels>
    ex: <input ng-repeat=(index, variable) in variables" type="text"
               my-name="{{ variable.name + '/' + 'myFormName' }}"
               ng-model="variable.name" required />
    ex: <select ng-model="variable.name" ng-options="label in label in {{ variable.options }}"
                my-name="{{ variable.name + '/' + 'myFormName' }}"

Note: you can add and index to the string concatenation if you need to serialize perhaps a table of inputs; which is what I did. However, dynamic name inputs means you may not know the name of the form input, so how would you call $scope.formName.??????. You could iterate of the $scope.formName object to get keys that match a certain value. That means string concatenation like this:

my-name="{{ dynamicString + hello + '/' + 'myFormName' }}"

Then in $scope.myFormName you would find any form input name by just iterating over the object and gathering any keys that included ‘hello’.

app.directive('myName', function(){

  var myNameError = "myName directive error: "

  return {
    restrict:'A', // Declares an Attributes Directive.
    require: 'ngModel', // ngModelController.

    link: function( scope, elem, attrs, ngModel ){
      if( !ngModel ){ return } // no ngModel exists for this element

      // check myName input for proper formatting ex. something/something

      var inputName = attrs.myName.match('^\w+').pop(); // match upto '/'
      assignInputNameToInputModel(inputName, ngModel);

      var formName = attrs.myName.match('\w+$').pop(); // match after '/'
      findForm(formName, ngModel, scope);
    } // end link
  } // end return

  function checkInputFormat(attrs){
    if( !/\w\/\w/.test(attrs.rsName )){
      throw myNameError + "Formatting should be \"inputName/formName\" but is " + attrs.rsName

  function assignInputNameToInputModel(inputName, ngModel){
    ngModel.$name = inputName

  function addInputNameToForm(formName, ngModel, scope){
    scope[formName][ngModel.$name] = ngModel; return

  function findForm(formName, ngModel, scope){
    if( !scope ){ // ran out of scope before finding scope[formName]
      throw myNameError + "<Form> element named " + formName + " could not be found."

    if( formName in scope){ // found scope[formName]
      addInputNameToForm(formName, ngModel, scope)
    findForm(formName, ngModel, scope.$parent) // recursively search through $parent scopes

This should handle many situations where you just don’t know where the form will be. Or perhaps you have nested forms, but for some reason you want to attach this input name to two forms up? Well, just pass in the form name you want to attach the input name to.

What I wanted, was a way to assign dynamic values to inputs that I will never know, and then just call $scope.myFormName.$valid.

This may be an overkill, and a better solution exists in 1.3+. I couldn’t find it in the time I had. This works for me now.

Good luck! Hope this helps someone!!!!


work for me with angular 1.2.7


var DynamicName = function() {
    return {
        restrict: 'A',
        priority: -1,
        require: ['ngModel'],
        link: function (scope, element, attr, ngModel) {
            ngModel[0].$name = attr.name;

app.directive('dynamicName', DynamicName);


<div ng-repeat="phone in hrModel.phones">
    <input type="text"


Compiling Your Input Name

  1. As someone else pointed out, modern versions of Angular have fixed this…
  2. This ought to set the name attribute on your input, and add the model controller to the form:
        .directive('compiledName', compiledNameDirective);

    function compiledNameDirective() {
        return {
            restrict: 'A',
            require: ['ngModel', '?^form'],
            scope: {
                name: '@compiledName'
            link: function checkboxIndeterminateLink(scope, element, attributes, required) {
                var ngModelController = required[0], ngFormController = required[1];
                ngModelController.$name = scope.name;
                element.attr('name', scope.name);
                if (ngFormController) ngFormController.$addControl(ngModelController);



Don’t forget that you can access javascript objects using array notation with string indexes. Given the following arbitrary form definition object :

$scope.form_def = {
  form_name : 'BallForm',
  variables : [
    height : { name : 'Height', type : 'text' },
    width : { name : 'Width', type : 'text' },
    color : { name : 'Color', type : 'multi', options : ['red', 'green', 'blue'] }
$scope.form_values = {};

… and the html snippet …

<form name="{{ form_def.form_name }}">
  <div ng-repeat="variable in form_def.variables">
    <input ng-if="variable.type==='text'" type="text" name="{{ variable.name }}" ng-model="form_values[variable.name]">
    <select ng-if="variable.type==='multi'" name="{{ variable.name }}" ng-model="form_values[variable.name]">
      <option ng-repeat="opt in variable.options" value="{{ opt }}">{{ opt }}</option>

Inside the controller you then would have a nice form_values object for every field which you can access by iterating over the keys in the form_def.variables hash.

There is a lot more involved once you get down into writing these sort of generic form processing scripts and you end up with a hell of a lot of spaghetti code in my opinion and you would probably be better of going with a less general solution, but thats another SO question.