A custom filter overrides the original data or causes an infinite $ digest loop

initial situation

TL DR
I want to filter a nested array using a special AngularJS filter. Unfortunately, not only the data for ng-repeat is filtered, but also the original object from $ scope.

I have a small demo as a fiddle for you: http://jsfiddle.net/7XRB2/
For example. find Testand the list will be shorter. Delete your search and you will see what happens: nothing. The filter does not filter the list, it filters the source data!

This is my filter:

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

I already implemented another custom search filter that works fine and does not have this problem:

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

I think the problem

topic.videos = tmpVideos; area.topics = tmpTopics; . , - javascripts - scope.

angular.copy() :

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

, angular.forEach

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

: http://jsfiddle.net/dTA9k/

$digest

Yippi! - ...
:

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

SO , , , - angular.copy.

, ?

+4
1

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>
0

Source: https://habr.com/ru/post/1529395/


All Articles