Yves Schelpe
Yves Schelpe

Reputation: 3463

Infinite $digest() loop AngularJS with filter expression on html attribute

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.

Upvotes: 1

Views: 890

Answers (2)

Frederik Prijck
Frederik Prijck

Reputation: 1509

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

Upvotes: 0

Mistalis
Mistalis

Reputation: 18269

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

Upvotes: 2

Related Questions