自定义过滤器覆盖原始数据或导致无限$digest循环。

4

初始情况

快速阅读
我想使用自定义的 AngularJS 过滤器过滤嵌套数组。不幸的是,不仅是 ng-repeat 的数据被过滤,$scope 中的原始对象也被过滤了。

我为您准备了一个小的演示代码:http://jsfiddle.net/7XRB2/
例如,请搜索 Test,列表将会变短。删除搜索内容,您会看到发生了什么:什么也没有发生。该过滤器并没有过滤 列表,它过滤的是 原始数据

这是我的过滤器:

app.filter('searchFilter', function() {
  return function(areas, searchTerm) {
    if (!angular.isUndefined(areas)
      && !angular.isUndefined(searchTerm)) {

      var searchExp;
      searchExp = new RegExp(searchTerm, 'gi');

      var tmpAreas = [];
      angular.forEach(areas, function(area) {
        var tmpTopics = [];
        angular.forEach(area.topics, function(topic) {
          var tmpVideos = [];
          angular.forEach(topic.videos, function(video) {
            if (video.title.match(searchExp)) {
              tmpVideos.push(video);
            }
          });
          topic.videos = tmpVideos;
          if (topic.videos.length > 0 || topic.title.match(searchExp)) {
            tmpTopics.push(topic);
          }
        });
        area.topics = tmpTopics;
        if (area.topics.length > 0) {
          tmpAreas.push(area);
        }
      });
      return tmpAreas;
    }
    else {
      return areas;
    }
  }
});

我已经实现了另一个自定义搜索过滤器,它运行良好且没有这个问题:

app.filter('mainNavigationFilter', function () {
  return function (elements, selectedElement) {
    if (!angular.isUndefined(elements) && !angular.isUndefined(selectedElement) && selectedElement.length > 0) {
      var tempElements = [];
      angular.forEach(selectedElement, function (id) {
        angular.forEach(elements, function (element) {
          if(angular.equals(element.id, id)
            tempElements.push(element);
          }
        });
      });
      return tempElements;
    }
    else {
      elements
    }
  }
});

我认为的问题

在我的过滤器中,我使用了topic.videos = tmpVideos;area.topics = tmpTopics;。由于 JavaScript 对象引用的原因,我猜想这些新赋值会被继承到原始对象 - 我的作用域对象。

经过一番研究,我找到了angular.copy()并在我的过滤器中添加了以下代码块:

var cpAreas;
cpAreas = angular.copy(areas);

此外,我将第一个angular.forEach更改为

angular.foreach(cpAreas, function(area) {[...]});

这里有一个更新的fiddle:http://jsfiddle.net/dTA9k/

无限$digest循环

太好了! 过滤器按预期工作 - 除非你打开控制台...
现在,过滤器引起了一个新问题:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [...]

我在SO上发现了一些关于这个错误的问题,看起来是由于angular.copy每次返回一个新对象导致的。

你有什么想法可以解决这个问题吗?


你的第二个例子似乎在Chrome中无法工作。 - BiAiB
1个回答

0

尝试使用自定义 ng-repeat。

所以我尝试了您的代码并使用了 $index。对于 topic.title 和 video.title,我不知道。尝试使用自定义 ng-repeat。

<div ng-app="videoList">
    <input ng-model='search' />
    <ul ng-controller='AreasController' class="video-list-areas">
        <li ng-repeat='area in filtered = (subject.areas | searchFilter:search)'>
            {{subject.areas[$index].title}}
            <ul>
                <li ng-repeat='topic in area.topics'>
                    <ul>
                        <li ng-repeat='video in topic.videos'>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

你的过滤器有效,我尝试在你的HTML中只使用了这个:

<div ng-app="videoList">
    <input ng-model='search' />
    <ul ng-controller='AreasController' class="video-list-areas">

        {{subject.areas | searchFilter:search}}


    </ul>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接