42

I would like to ask you if you can give me a hand on this.

I have created a jsfiddle with my problem here. I need to generate dynamically some inputs with ng-model in a ng-repeater using the way ng-model="my_{{$index}}".

In jsfiddle you can see that everything it's working fine until I try to generate it dynamically.

The html would be:

<div ng-app>
<div ng-controller="MainCtrl">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
  <tr>
    <td>
      <select ng-model="selectedQuery" 
        ng-options="q.name for q in queryList" >
        <option title="---Select Query---" value="">---Select Query---</option>
      </select>
    </td>
  </tr>
  <tr ng-repeat="param in parameters">
    <td>{{param}}:</td>
    <td><input type="text" ng-model="field_X" />field_{{$index}}</td>
  </tr>
</table>
<div>
<div>

And the javascript...

function MainCtrl($scope) {
 $scope.queryList = [
    { name: 'Check Users', fields: [ "Name", "Id"] },
    { name: 'Audit Report', fields: [] },
    { name: 'Bounce Back Report', fields: [ "Date"] } 
  ];

$scope.$watch('selectedQuery', function (newVal, oldVal) {
    $scope.parameters = $scope.selectedQuery.fields;
  });
}

Can you give me any idea?

Thanks a lot.

Federico Piazza
  • 30,085
  • 15
  • 87
  • 123
  • possible duplicate of [How can I set a dynamic model name in AngularJS?](http://stackoverflow.com/questions/12553617/how-can-i-set-a-dynamic-model-name-in-angularjs) –  Nov 10 '14 at 20:40

6 Answers6

46

Does it solve your problem?

function MainCtrl($scope) {
     $scope.queryList = [
        { name: 'Check Users', fields: [ "Name", "Id"] },
        { name: 'Audit Report', fields: [] },
        { name: 'Bounce Back Report', fields: [ "Date"] } 
      ];
    $scope.models = {};
    $scope.$watch('selectedQuery', function (newVal, oldVal) {
        if ($scope.selectedQuery) {
            $scope.parameters = $scope.selectedQuery.fields;
        }
    });
}

And in your controller:

  <tr ng-repeat="param in parameters">
    <td>{{param}}:</td>
    <td><input type="text" ng-model="models[param] " />field_{{$index}}</td>
  </tr>

Fiddle

Beterraba
  • 6,515
  • 1
  • 26
  • 33
24

What you could do is to create an object on a scope (say, values) and bind to the properties of this object like so:

<input type="text" ng-model="values['field_' + $index]" />

Here is a jsFiddle illustrating the complete solution: http://jsfiddle.net/KjsWL/

pkozlowski.opensource
  • 117,202
  • 60
  • 326
  • 286
  • You are tracking through the $index which is/will be unique for each row. If I need to track also on the colum basis, what would you suggest? I mean values[$index][columnIndex] ...How to give this column index? – Farhan stands with Palestine Nov 03 '16 at 08:18
4

I did elaborate my answer from pkozlowski's and try to generate a dynamic form, with dynamic ng-model:

<form ng-submit="testDynamic(human)">
    <input type="text" ng-model="human.adult[($index+1)].name">
    <input type="text" ng-model="human.adult[($index+1)].sex">
    <input type="text" ng-model="human.adult[($index+1)].age">
</form>

But first, we need to define the 'human' scope inside our controller

$scope.human= {};

And then, on submission we will have the data like this (depending on how much field is generated):

var name = human.adult[i].name;
var sex = human.adult[i].sex;
var age = human.adult[i].age;

It's pretty straightforward and I hope my answer helps.

FirdhausKM
  • 85
  • 1
  • 9
1

Is there a reason to generate those field names? Can you treat each field as an object with name and value instead of a string name? (FIDDLE)

function MainCtrl($scope) {
     $scope.queryList = [
         { name: 'Check Users', fields: [ { name: "Name" },  { name: "Id" } ] },
         { name: 'Audit Report', fields: [] },
         { name: 'Bounce Back Report', fields: [ { name: "Date" } ] } 
      ];
}

And just repeat off of selectedQuery.fields:

<tr ng-repeat="field in selectedQuery.fields">
    <td>{{field.name}}:</td>
    <td><input type="text" ng-model="field.value" /></td>
</tr>
Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
  • I need that in order to generate queries to mongodb, and this queries are previously stored in a collection. The idea of this is fetch this queries and execute each query to mongo. – Federico Piazza Oct 24 '13 at 20:07
  • By the way, both solution above have helped me to solve the trouble. Thanks – Federico Piazza Oct 24 '13 at 20:08
0

Beterraba's answer was very helpful for me. However, when I had to migrate the solution to Typescript it wouldn't behave for me. Here is what I did instead. I expanded the individual parameters (fields on the queryList in your example) into full objects that included a "value" field. I then bound to the "value" field and it worked great!

Originally you had:

[
  { name: 'Check Users', fields: [ "Name", "Id"] },
    ...
  }
]

I changed it to something like this:

[
  { name: 'Check Users', fields: [
                                    {Text:"Name",Value:""},
                                    {Text:"Id",Value:0}],
                                    ...
                                   ]
  }
]

...and bound to the 'Value' sub-field.

Here is my Typescript if you care.

In the html:

<div ng-repeat="param in ctrl.sprocparams" >
    <sproc-param param="param" />
</div>

In the sproc-param directive that uses Angular Material. See where I bind the ng-model to param.Value:

return {
    restrict: 'E',
    template: `
                <md-input-container class="md-block" flex-gt-sm>
                    <label>{{param.Name}}</label>
                    <input  name="{{param.Name}}" ng-model=param.Value></input>
                </md-input-container>`,
    scope: {
            param: "="
        }
}
Jeff Lehmer
  • 241
  • 1
  • 5
  • 17
0

I need to generate dynamically some inputs with ng-model in a ng-repeater using the way ng-model="my_{{$index}}".

One can use the this identifier with a bracket notation property accessor:

  <tr ng-repeat="param in parameters">
    <td>{{param}}:</td>
    <td>
      <input type="text" ng-model="this['my_'+$index]" />
      my_{{$index}}
    </td>
  </tr>

It is possible to access the $scope object using the identifier this.

For more information, see

georgeawg
  • 48,608
  • 13
  • 72
  • 95