1

When I try to pass a filter expression inside a component's attribute, e.g. (see this Plunker example as well, and the possible solutions listed below).

<todo-list todos="$ctrl.todos | filter:{type:1}"></todo-list>

I get an error on the infinite digest loop, I don't understand why:

Error: [$rootScope:infdig] http://errors.angularjs.org/1.6.3/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22ms…e%2C%22type%22%3A1%2C%22%24%24hashKey%22%3A%22object%3A5%22%7D%5D%7D%5D%5D
    at eval (angular.js:38)
    at m.$digest (angular.js:18048)
    at m.$apply (angular.js:18280)
    at eval (angular.js:1912)
    at Object.invoke (angular.js:5003)
    at c (angular.js:1910)
    at Object.Pc [as bootstrap] (angular.js:1930)
    at execute (VM877 main.ts!transpiled:21)
    at f (system.js:5)
    at Object.execute (system.js:5)

Code, see Plnkr: http://plnkr.co/edit/JdiLEIyji2pHd3eeNMUL?p=preview

Screenshot / Image: enter image description here

Workaround/solution: I have several workarounds/solutions:

  1. In the repo where I had the problem at first: I did <todo-list todo-items="$ctrl.todoItems" filter-by="{completed:true}"></todo-list>. For full source see here: https://github.com/aredfox/todo-angularjs-typescript/commit/e71900b96173b63ebcebb8e6c1fba00fe3997971. But I feel it's working around the problem, plus I don't understand why this triggers a $digest() cycle and why it shouldn't just work.

  2. Answer by @Mistalis https://stackoverflow.com/a/43120388/1155847 whogave a somehwat similar solution.

Community
  • 1
  • 1
Yves Schelpe
  • 3,343
  • 4
  • 36
  • 69

2 Answers2

2

The goal of filter is to get an array as input and return another array based on some rules and conditions, where array items have the same structure as input.

The reason that causes an infinite loop in the $digest cycle is that in a filter, each digest cycle filter returns a different object that causes an additional cycle. - Source


I would suggest you to move the filter to the todoList directive:

<div ng-repeat="todo in $ctrl.todos | filter: {type:1}">
    <span>{{todo.name}}</span>
</div>

If type needs to be dynamic, pass it as a parameter/attribute to the directive.

Forked your Plunker

Community
  • 1
  • 1
Mistalis
  • 17,793
  • 13
  • 73
  • 97
  • Thanks @mistalis I have a similar solution for it in my repo where I had the problem at first: ``. For full source see here: https://github.com/aredfox/todo-angularjs-typescript/commit/e71900b96173b63ebcebb8e6c1fba00fe3997971. **But** I feel it's working around the problem, I don't understand why this triggers a *$digest()* cycle and why it shouldn't just work? I'll also edit this in my question to reflect this. +1'ed though because indeed that's for me now the way to go :/... – Yves Schelpe Mar 31 '17 at 05:03
  • 1
    The goal of filter is to get an array as input and return another array based on some rules and conditions, where array items have the same structure as input. The reason that causes an infinite loop in the $digest cycle is that in a filter, each digest cycle filter returns a different object that causes an additional cycle. [**This question**](http://stackoverflow.com/questions/22066919/angular-infinite-digest-loop-in-filter) deals well with this subject. – Mistalis Mar 31 '17 at 06:59
  • 1
    See https://github.com/angular/angular.js/issues/14039 for more about this issue. – Frederik Prijck Mar 31 '17 at 07:33
0

There's an open issue at the angular.js repo you can follow up on in order to see the evolution regarding this problem: https://github.com/angular/angular.js/issues/14039

As a temporary solution, you could change your binding to use a shallow two way binding by changing < to =* as mentioned here: https://github.com/angular/angular.js/issues/14039#issue-133588717 Il8PNgcE?p=preview

Frederik Prijck
  • 1,424
  • 10
  • 16
  • 1
    If you downvote this answer, could you elaborate leaving a comment why you did so? As this involves / points to reactions of the angularjs core team themself I find this rather usefull. The biggest advantage of this workaround is that it doesn't require any refactoring once `<*` get's supported. We're discussing the same workaround over at: https://github.com/angular/angular.js/issues/15874 btw. So feel free to explain us over there aswell why you are against it. – Frederik Prijck Mar 31 '17 at 08:16
  • Accepted this as correct answer as it corresponds with the solutions provided on the angularjs github issue (http://github.com/angular/angular.js/issues/15874) on this topic. – Yves Schelpe Mar 31 '17 at 09:37