admin管理员组

文章数量:1332345

I defined a 2D array in a controller but when I try to loop over it, with 2 imbricated loops, it not works as exepected. The first loop works fine but the second one is not working.

js/index.js

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

gameOfLifeApp.controller('fieldCtrl', function ($scope) {
    $scope.field = [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ];
});

index.html

<!DOCTYPE HTML>
<html ng-app="gameOfLifeApp">
<head>

    <meta charset="UTF-8">
    <title>Game of Life</title>
    <link rel="stylesheet" href="css/style.css">
    <script src=".2.13/angular.min.js"></script>
    <script src="js/index.js"></script>

</head>
<body ng-controller="fieldCtrl">

<div id="field">
    <div class="column" ng-repeat="column in field">
        <div class="cell" ng-repeat="cell in column"></div>
    </div>
</div>

</body>
</html>

output:

<body ng-controller="fieldCtrl" class="ng-scope">
<div id="field">
    <!-- ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
</div>
</body>

What did I do wrong ?

I defined a 2D array in a controller but when I try to loop over it, with 2 imbricated loops, it not works as exepected. The first loop works fine but the second one is not working.

js/index.js

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

gameOfLifeApp.controller('fieldCtrl', function ($scope) {
    $scope.field = [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ];
});

index.html

<!DOCTYPE HTML>
<html ng-app="gameOfLifeApp">
<head>

    <meta charset="UTF-8">
    <title>Game of Life</title>
    <link rel="stylesheet" href="css/style.css">
    <script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.13/angular.min.js"></script>
    <script src="js/index.js"></script>

</head>
<body ng-controller="fieldCtrl">

<div id="field">
    <div class="column" ng-repeat="column in field">
        <div class="cell" ng-repeat="cell in column"></div>
    </div>
</div>

</body>
</html>

output:

<body ng-controller="fieldCtrl" class="ng-scope">
<div id="field">
    <!-- ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
    <div class="column ng-scope" ng-repeat="column in field">
        <!-- ngRepeat: cell in column -->
    </div>
    <!-- end ngRepeat: column in field -->
</div>
</body>

What did I do wrong ?

Share Improve this question edited Feb 20, 2014 at 7:56 Co_42 asked Feb 20, 2014 at 7:48 Co_42Co_42 1,2691 gold badge11 silver badges19 bronze badges 1
  • jsfiddle/mtMD5/2 does this work ok? – Tudor Zgureanu Commented Feb 20, 2014 at 7:57
Add a ment  | 

2 Answers 2

Reset to default 8

You cannot use this. Angular cannot keep track of each cell if they are non-object identical. To over ride this use track by keyword and use the $index for tracking.

<div id="field">
    <div class="column" ng-repeat="column in field">
        <div class="cell" ng-repeat="cell in column track by $index"></div>
    </div>
</div>

Ok, this is funny, it turns out one row in a dataset repeating the same values, as in your data set:

$scope.field = [
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
];

Or similarly, the following dataset (to clarify my explanation, ie: "row");

$scope.field = [
    [0, 0, 0],
    [1, 1, 1],
    [2, 2, 2]
]; //notice that each "column" in a row repeats the exact same value

Is not allowed in angular, and breaks it, therefore if you right click -> inspect element, you'll get an error talking about duplicates. If however, you changed the dataset, for each "column" in a "row" to have it's own value, it will work as expected, like this;

$scope.field = [
    [1, 2, 3],
    [3, 1, 2],
    [3, 2, 1]
];

you can read more on this in the first answer here

//so to reference the relevant extract from that answer, the answer to your question is:

AngularJS does not allow duplicates in a ng-repeat directive. This means if you are trying to do the following, you will get an error.

// the below will throw the error Duplicates in a repeater are not allowed. Repeater: row in [1,1,1] key: number:1 <div ng-repeat="row in [1,1,1]"> However, changing the above code slightly to define an index to determine uniqueness as below will get it working again.

// this will work <div ng-repeat="row in [1,1,1] track by $index">

it waould also help to mention that you can apply any custom tracking property to define uniqueness, not just $index. Since in this scenario the objects don't have any other properties this works fine. The reason this error happens is that angular is using a dictionary to store the id of an item as the key with the value as the DOM reference. From the code (line 15402 in angular.js) it looks like they are caching previously found DOM elements based on their key as a performance optimization. Since they need unique keys they explicitly throw this error when they find duplicate keys on line 15417

本文标签: javascriptangularjs 2D array ngrepeat not working properlyStack Overflow