簡體   English   中英

Angular.js 1.4.7動態ng-options導致多個方法調用和infdig錯誤

[英]Angular.js 1.4.7 dynamic ng-options causing mutiple method calls and infdig errors

我有一個選擇列表,其中的內容是根據第一個選擇列表中選擇的內容動態生成的。 我似乎無法找到為什么每次更改第一個選擇列表時都會引發這些錯誤的原因:

Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [[{"msg":"fn:
regularInterceptedExpression","newVal":42,"oldVal":37},{"msg":"fn:       regularInterceptedExpression","newVal":"16","oldVal":"14"}],[{"msg":"fn: regularInterceptedExpression","newVal":47,"oldVal":42},{"msg":"fn: regularInterceptedExpression","newVal":"18","oldVal":"16"}],[{"msg":"fn: regularInterceptedExpression","newVal":52,"oldVal":47},{"msg":"fn: regularInterceptedExpression","newVal":"20","oldVal":"18"}],[{"msg":"fn: regularInterceptedExpression","newVal":57,"oldVal":52},{"msg":"fn: regularInterceptedExpression","newVal":"22","oldVal":"20"}],[{"msg":"fn: regularInterceptedExpression","newVal":62,"oldVal":57},{"msg":"fn: regularInterceptedExpression","newVal":"24","oldVal":"22"}]]
http://errors.angularjs.org/1.4.7/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22ms…Expression%22%2C%22newVal%22%3A%2224%22%2C%22oldVal%22%3A%2222%22%7D%5D%5D

另外,每次更改列表時,列表的每次更改都會觸發幾次用於生成第二個列表的“ makeOptions”。

這兩個列表的設置如下:

    <select ng-model="selected.level1" ng-options="lvl.name as lvl.name for lvl in level1options"></select>
    <select ng-model="selected.level2" ng-options="opt.value as opt.label for opt in makeOptions()"></select>

控制器是:

app.controller('DemoController', function($scope) {

  $scope.level1options = [{ name: "A", value: "A" }, { name: "B", value: "B" }, { name: "C", value: "C" }];
  $scope.makeOptionsCallCount = 1;
  $scope.selected = {};


  $scope.makeOptions = function() {

    console.log($scope.makeOptionsCallCount++);

    var options = [];

    for (var i = 0; i < 5; i++) {
        options.push({ label: 'Value = ' + i + $scope.selected.level1, value: i + $scope.selected.level1 });
    }

    return options;
  };

});

這是個奇怪的例子:

http://plnkr.co/edit/mKv7nMjot5XqBj4mkvhR?p=preview

有什么想法我做錯了嗎?

更新

我可能已經簡化了遇到麻煩的示例。 解決方案變得更加復雜,因為我有一個項目列表,您可以為每個項目選擇一組值。 我很抱歉,問我最初的問題時,我忽略了這個要素。

我創建了一個新示例,可以更准確地反映這一點:

http://plnkr.co/edit/I62WepJVLuuqN0YbCafD?p=preview

當您在視圖內部使用函數時,它將在每個摘要循環上執行。

也可以使用角度添加觀察器來實現此功能,例如,如果您在每次調用時都返回新數組-您將進入無限循環,因為[] != []

在您的情況下,您還有另一個錯誤:在視圖中調用的內部函數更改了變量,該函數也在視圖中顯示。 因此,為此變量還添加了監視程序。

您可以在函數調用中更改值,觀察變量是否已更改,再次運行摘要,運行函數,更改值,變量是否已更改等...

因此,對於解決方案,更好的簡單更改保存選項是首先選擇的。

 var app = angular.module('demoApp', []) app.controller('DemoController', function($scope) { $scope.level1options = [{ name: "A", value: "A" }, { name: "B", value: "B" }, { name: "C", value: "C" }]; $scope.makeOptionsCallCount = 1; $scope.selected = {}; $scope.makeOptions = function(lvl) { $scope.options = []; console.log(++$scope.makeOptionsCallCount); for (var i = 0; i < 5; i++) { $scope.options.push({ label: 'Value = ' + i + lvl, value: i + lvl }); } }; }); 
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script> <div ng-app="demoApp" ng-controller="DemoController"> <div> <h2>Infinite Digest 2</h2> <select ng-model="selected.level1" ng-options="lvl.name as lvl.name for lvl in level1options" ng-change="makeOptionsCallCount=0;makeOptions(selected.level1)"></select> <select ng-model="selected.level2" ng-options="opt.value as opt.label for opt in options"></select> <br/> <br/> <div>Level 1: {{selected.level1}}</div> <div>Level 2: {{selected.level2}}</div> <div>makeOptions() Called: {{makeOptionsCallCount}} times</div> </div> </div> 

更新:
就您的評論而言,您可以利用ng-repeat創建自己的作用域,並將在ng-change事件上創建的列表選項保存到該作用域這一事實。

同樣,您甚至可以使用函數makeOptions

要進行ng-change ,可以傳遞表達式:

ng-change="optionsLvLs = makeOptions(option.level1)"

在每個選項的ng-repeat范圍中,如果發生問題,將在change事件上創建不會污染您的選項對象的optionsLvLs

  var app = angular.module('demoApp', []) app.controller('DemoController', function($scope) { $scope.level1options = [{ name: "A", value: "A" }, { name: "B", value: "B" }, { name: "C", value: "C" }]; $scope.selected = {}; $scope.options = [{ name: "A" }]; $scope.makeOptions = function(level1) { var options = []; for (var i = 0; i < 5; i++) { options.push({ label: 'Value = ' + i + level1, value: i + level1 }); } return options; }; $scope.addQuery = function(idx) { $scope.options.splice(idx + 1, 0, {}); }; $scope.removeQuery = function (idx) { $scope.options.splice(idx, 1); }; }); 
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script> <div ng-controller="DemoController" ng-app="demoApp"> <div> <h2>Infinite Digest 2</h2> <div ng-repeat="option in options"> <input type="button" value="+" ng-click="addQuery($index)" /> <input type="button" value="-" ng-click="removeQuery($index)" /> <select ng-model="option.level1" ng-options="lvl.name as lvl.name for lvl in level1options" ng-change="optionsLvLs = makeOptions(option.level1)"></select> <select ng-model="option.level2" ng-options="opt.value as opt.label for opt in optionsLvLs"></select> <br/> <br/> </div> </div> {{ options }} </div> 

做下面的變化也不會要求調用一個函數,以動態地創建數據:

$scope.level1options = [{ name: "A", value: "A" }, { name: "B", value: "B" }, { name: "C", value: "C" }];
$scope.level2options = [0,1,2,3,4];

<select ng-model="selected.level1" ng-options="lvl.name as lvl.name for lvl in level1options"></select>
<select ng-model="selected.level2" ng-options="i+selected.level1 as 'Value = '+i+selected.level1 for i in level2options"></select>

這里的plunker: http://plnkr.co/edit/GQhnjTpB0sLHoiSnchhn?p=preview

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM