Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying objects within Angular Scope inside ng-repeat

I'm creating a form in HTML using ng-repeat to generate the form elements from an object in the scope. I also use that object to generate other elements outside of the ng-repeat.

A simplified example looks like this in HTML:

<div ng-app="App">
  <div ng-controller="Ctrl">
      <div class="block1">
          <form ng-repeat="(key, value) in test">
              <label>{{key}}</label>
              <input ng-model="value" />
              <p>{{value}}</p>
          </form>
      </div>
      <div class="block2">
        <p>
          {{test.a}}
        </p>
        <p>
            {{test.b}}
        </p>
      </div>
  </div>
</div>

and this in JS:

angular.module('App', []);

function Ctrl($scope) {
    $scope.test = {
        a:"abc",
        b:"def"
    }
}

In this example, the text in block2 is set to the initial values of test.a and test.b. The input values and <p> values inside of the loop are also set to the initial value.

When I modify the values within the inputs, the <p> values inside of the ng-repeat block update correctly, but the <p> tags in block2 fail to update.

Why is this the behavior? Does ng-repeat create its own isolated scope? If so how can I get the controller level scope to update? Also, could somebody explain the thinking behind this behavior and any advantages it provides?

JSFiddle Showing the problem

like image 784
Ben McCormick Avatar asked Dec 14 '13 23:12

Ben McCormick


1 Answers

ng-repeat creates a child scope for each repeated item. As a result you are trying to pass a primitive to child scope which won't create a reference to parent. When you pass objects however, you pass the original object reference.

From the mouth of one of the fathers of Angular:

Always have a dot in ng-model

This is a great video regarding Angular Best Practices given by Angular creator (2012/12/11). Go to minute 31 for well explained detail of this exact situation

Modify data to array of objects:

$scope.test = [{ val:"abc",key:'a'}, {val:"def",key:'b'} ]

Then in repeater:

<form ng-repeat="item in test">
  <label>{{item.key}}</label>
  <input ng-model="item.val" />
  <p>{{item.val}}</p>
</form>

DEMO

like image 86
charlietfl Avatar answered Oct 04 '22 20:10

charlietfl