1

This is something that i have runned in a couple of times.

Say i have the following variables in my controller:

$scope.valueArr = ['Hello', 'No', 'Yes'];
$scope.myValue = 'Hello';

And i have the following ng-repeat:

<li ng-repeat="value in valueArr" ng-class="{'active' :  myValue == value}"><a>{{value}}</a> </li>

Now if i do the following:

<a ng-click="myValue = value"> </a>

Then it adds the class to the li however it does remove the class from the previous li

But if i do the following:

<a ng-click="setMyValue(value);"> </a>

and in my controller add the function:

$scope.setMyValue = function(value){$scope.myValue = value}

Then it removes the "old" and only adds the active class to the last pressed li

So it seems that it is not rerendering without a function in the controller. Can anyone tell me why? and when you should choose one over the other.

Note this is just one of many examples where the rerendering is not happening.

Marc Rasmussen
  • 19,771
  • 79
  • 203
  • 364
  • javascript objects are weird. There's a general piece of advice for angular applications, and it's "Always use a dot." By always using a dot, you are going to be dealing with object properties, which angular is great at binding with. Sometimes binding to primitives gets really weird. See this [SO answer](http://stackoverflow.com/a/14049482/4320665) – ryanyuyu Oct 21 '15 at 12:56

2 Answers2

3

This is because ng-repeat creates a child scope refer the DOC.

that means there is a separate scope for each repeat

there is a separate child scope for first repeat.

there is a separate child scope for second repeat.

there is a separate child scope for third repeat.

... like wise

SO if you access a variable (myValue) as ng-click="myValue = value" angular search in the repeat's child scope and after realize there is no variable called myValue or no any other references to access then create a myValue on the child scope. How ever you can access the parent scope by using $parent.myValue.

check the DEMO


another way to do this is use a object like,

$scope.tempObj = {myValue : 'Hello'};

and refer this by using

<a ng-click="tempObj.myValue = value">

since myValue is a object property (object of tempObj) then if angular realize there is no tempObj object in the child scope it will search for the parent's scopes.


If you using

<a ng-click="setMyValue(value);"> </a>

&

$scope.setMyValue = function(value){$scope.myValue = value}

in setMyValue function it uses $scope.myValue which is in the controller scope not in the repeat's child scope.

Community
  • 1
  • 1
Kalhan.Toress
  • 21,683
  • 8
  • 68
  • 92
  • The part about `there is no variable` is wrong. It will be in the child scope if it existed in the controller scope. But it is a primitive and doesn't have inheritance – charlietfl Oct 21 '15 at 13:00
  • Why it does not create a new object for the child scope like it creates new variable for child scope? – User2 Oct 21 '15 at 13:18
  • @User2 check this answer http://stackoverflow.com/questions/17606936/angularjs-dot-in-ng-model – Kalhan.Toress Oct 21 '15 at 16:00
2

ng-repeat creates a new child scope for each of the repeated elements. So when you write

<a ng-click="myValue = value"> </a>

You are creating the new variable 'myValue' on the child scope of the <li> when the user clicks the button. This hides the value of 'myValue' on the parent scope, but doesn't change it - so all the other <li> scopes are still inheriting the value of 'myValue' from the parent scope.

However, when you write

<a ng-click="setMyValue(value);"> </a>

you are referencing the function setMyValue defined on the parent scope. Therefore when the user clicks the button the setMyValue function is executed and sets 'myValue' on the parent scope. The child scope is not touched. Because the value is changed on the parent scope, all the <li> elements inherit it.

Oliver
  • 11,297
  • 18
  • 71
  • 121