Angular.js 1.4.7动态ng-options导致多个方法调用和infdig错误 [英] Angular.js 1.4.7 dynamic ng-options causing mutiple method calls and infdig errors

查看:46
本文介绍了Angular.js 1.4.7动态ng-options导致多个方法调用和infdig错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个选择列表,其中的内容是从第一个选择列表中选择的内容动态生成的.我似乎无法找到为什么每次更改第一个选择列表时都会触发这些错误的原因:

I have a select list where the content is dynamically generated from the content selected in the first select list. I cant seem to find why I'm getting these errors fired every time the first select list is changed:

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".

Plus each time the list is changed, the "makeOptions" used to generate the second list is fired several times per single change of the list.

两个列表的设置如下:

    <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;
  };

});

下面是一个奇怪的例子:

Here is an example of what is going weird:

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

有什么想法我做错了吗?

Any ideas where I've gone wrong?

更新

在遇到麻烦的示例中,我可能已经简化了.解决方案变得更加复杂,因为我有一个项目列表,您可以为每个项目选择一组值.我很抱歉,在问我最初的问题时,我忽略了这个要素.

I may have over simplified the example where I was having troubles. The solution becomes more complex because I have a list of items where for each item you can choose a set of values. I apologize, I overlooked this element when asking my original question.

我创建了一个新示例,可以更准确地反映出这一点:

I have created new example that more accurately reflects this:

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

推荐答案

在视图内使用函数时,它将在每个摘要循环上执行.

When you use function inside view, it execute on every digest loop.

也可以使用角度添加观察器来实现此功能,例如,如果您在每次调用时都返回新数组-您将进入无限循环,因为 []!= []

Also angular add watcher to result this function, and if you, for example, return new array on every call - you go to infinit loop, because [] != []

在您的情况下,您还有另一个错误:在视图中调用的内部函数会更改变量,该函数也在视图中显示.因此,还为该变量添加了监视程序.

In your case, you have also another error: inside function that called in view you change variable, that also showed in view. So for this variable also added watcher.

您在函数调用中更改了值,看到变量已更改,再次运行摘要,运行函数,更改值,看到变量已更改等...

You change value in function call, watch see that variable changed, run digest again, run function, change value, see that variable changed and etc...

因此,对于解决方案,最好先选择更改时更好的简单保存选项.

So, for solution, better simple save options on change first select.

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 事件上创建的列表选项保存到其中的事实.

UPDATE:
In your case from comment, you can take advantage of the fact that ng-repeat create own scope, and save to it list options, created on ng-change event.

此外,您甚至可以使用函数 makeOptions .

also, you can even use your function makeOptions.

要进行 ng-change ,您可以传递表达式:

To ng-change you can pass expression:

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

对于每个选项,在 ng-repeat 范围内,将在更改事件上创建 optionsLvLs ,它不会污染您的 option 对象,如果这样做很重要.

here in ng-repeat scope for every option, on change event would be created optionsLvLs that not pollute your option object, if this was matter.

    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>

这篇关于Angular.js 1.4.7动态ng-options导致多个方法调用和infdig错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆