NoWhereToBeSeen
NoWhereToBeSeen

Reputation: 1444

why do two ng-repeats share same scope?

I have two divs with ng-repeat of the same list. But when I change the content of one list item from first div, the second div receives the same value. I thought ng-repeats had isolated scopes? How can I archieve isolation of the ng-repeats?

edit: "In most cases, directives and scopes interact but do not create new instances of scope. However, some directives, such as ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element." http://docs.angularjs.org/guide/scope

<div ng-controller="MyCtrl">
<button ng-click="newitem()">add item </button>
<div ng-repeat="item in list">
    <input ng-model="item.name" placeholder="Name*">
    <input ng-model="item.lastname" placeholder="Last name*">
    <input ng-model="item.username" placeholder="Username(Email)*">
</div>
        here is another div with ng-repeat of the same list. why do they share scope? 
        <br>
<div ng-repeat="item in list">
    <input ng-model="item.name" placeholder="Name*">
    <input ng-model="item.lastname" placeholder="Last name*">
    <input ng-model="item.username" placeholder="Username(Email)*">
</div>

js:

 var myApp = angular.module('myApp', []);
function MyCtrl($scope) {

$scope.list = [];

$scope.newitem = function () {
    $scope.list.push({name: "", lastname: "", username: ""});
}
}

http://jsfiddle.net/LZKq2/

Upvotes: 2

Views: 1514

Answers (3)

Claies
Claies

Reputation: 22323

I'll try to explain this in a different way than the other answers, though all answers are basically saying the same thing.

When you attach the controller to the div element, it creates an instance of the controller with the $scope attached to it, to which you add an array. The moment that you attach the array to the first child div and use ng-repeat, you get a child scope that belongs to the array. the second child div is not creating a new array but re-using an existing array which now already has a scope. Thus, items added into the array via the first div are reflected in the second div. It could not possibly function in any other way, as you only have one variable that you are tracking across the $scope. If, however, you had 2 separate lists, say $scope.list and $scope.list2, these 2 arrays would each have their own scope. see http://jsfiddle.net/zTE5j/2/

<div ng-controller="MyCtrl">
<button ng-click="newitem()">add item </button>
<div ng-repeat="item in list">
    <input ng-model="item.name" placeholder="Name*">
    <input ng-model="item.lastname" placeholder="Last name*">
    <input ng-model="item.username" placeholder="Username(Email)*">
</div>
        here is another div with ng-repeat of the same list. why do they share scope? 
        <br>
<div ng-repeat="item in list2">
    <input ng-model="item.name" placeholder="Name*">
    <input ng-model="item.lastname" placeholder="Last name*">
    <input ng-model="item.username" placeholder="Username(Email)*">
</div>
</div>

controller:

var myApp = angular.module('myApp', []);

function MyCtrl($scope) {

$scope.list = [];
$scope.list2 = [];

$scope.newitem = function () {
    $scope.list.push({name: "", lastname: "", username: ""});
    $scope.list2.push({name: "", lastname: "", username: ""});
}
}

Upvotes: 2

Jeremy Likness
Jeremy Likness

Reputation: 7521

The new scopes are child scopes so although the scope is new, the properties on the scope are inherited from the parent. For example, if the parent has a list of items, then child scopes inherit the same list of items. Think of it as "pointers to the parent list." When you modify item "x" in the first list, item "x" is in a list on the scope. That list is inherited from the parent list, so modifying "item x" is the same as modifying that item in the parent list. Because the second list inherits from the parent, it also has the same reference to "item x" and therefore it will reflect the update.

This is demonstrated in this fiddle: http://jsfiddle.net/jeremylikness/xdzxb/

Note both lists are affected when you edit an item, but the third list isn't because it was created as a copy:

$scope.listNew = $scope.list.slice(0);

You'll need to explicitly create copies if you want the repeats to act on different versions of the list.

Upvotes: 1

Royi Namir
Royi Namir

Reputation: 148574

ng-repeat do creates new scope according to angularjs.

but do you have toString in a plain object ?

var a={};
if (a.toString) alert('1');// ( where the hell this toString came from ?)

this will alert 1 !!!

this is because of prototype inheritance.

your inline repeat scope has its own scope which SEEK FOR ITS PARENT SCOPE for data ( if not found).

why do they share scope?

Becuase they are both seeing the same viewmodel object , $scope which is created by the controller.

Upvotes: 0

Related Questions