Search code examples
angularjsangularjs-ng-repeatangular-ngmodel

angularjs two-way binding inside ng-repeat


I have an Angular controller variable defining the look-and-feel of a bunch of fields which I want to render in a template. The initial value of my underlying model correctly appears in the input element, but it doesn't change when I change the content of that element.

Here is some code:

app.js

(function() {
  var app = angular.module("my_app", []);
    app.controller("MyController", function() {
      var my_controller = this;
      my_controller.model = {
        "first_name": "fred",
        "last_name": "jones"
      }
      my_controller.fields = [
         {
          "name": "first_name",
          "label": "First Name",
          "is_required": true,
          "model": my_controller.model.first_name
         },
        {
          "name": "last_name",
          "label": "Last Name",
          "is_required": true,
          "model": my_controller.model.last_name
         }
       ]
})();

template.html:

<div ng-app="my_app">
  <div ng-controller="MyController as my_controller">
    <div ng-repeat="field in my_controller.fields">
      {% verbatim ng %}
        <label for="id_{{ field.name }}" ng-class="field.is_required ? 'required' : 'optional'">{{ field.label }}:&nbsp;</label>
        <input type="{{ field.type }}" class="form-control" name="{{ field.name }}" id="id_{{ field.name }}" ng-model="field.model">
      {% endverbatim ng %}
     </div>
  </div>
</div>

(Don't worry about the "{% verbatim ng %}" stuff - that's just there b/c I'm using Django.)

This correctly displays two input fields with an initial value of "fred" and "jones" respectively. But when I change the value in those fields, there is no corresponding change to the my_controller.model object.

Any hints?

Thanks.


Solution

  • Doing this "model": user_controller.model.first_name will just assign value to the model field and it will not create a reference to my_controller.model.field_name.

    You can simply use bracket notation to modify the my_controller.model fields:

    angular.module('app', [])
    .controller('testController',
      function testController($scope) {
      
          var my_controller = this;
          
          my_controller.model = {
            first_name: "fred",
            last_name: "jones"
          };
          
          my_controller.fields = [
             {
              "name": "first_name",
              "label": "First Name",
              "is_required": true
             },
            {
              "name": "last_name",
              "label": "Last Name",
              "is_required": true
             }
           ];
           
    });
    <body ng-app="app">
    <div class="table-responsive" ng-controller="testController as my_controller">
          <div ng-repeat="field in my_controller.fields">
      
            <label for="id_{{ field.name }}" ng-class="field.is_required ? 'required' : 'optional'">{{ field.label }}:&nbsp;</label>
            <input type="{{ field.type }}" class="form-control" name="{{ field.name }}" id="id_{{ field.name }}" ng-model="my_controller.model[field.name]">
    
         </div>
         -----------------------------------
         <br/>
         <code>{{my_controller.model}}</code>
    </div>
    </body>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>