Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum call stack size exceeded in angularJS, when I try use | filter:searchText

Tags:

angularjs

I try to filter data using |filter in the ng-repeat directive.

 ng-repeat="item in transactions |filter:searchText"

transactions is array with data, which looks like this:

{
$$hashKey: "object:666",
amount: -50,
card: "3158",
catId: 0,
dateTime: {month: 2, value: "2015-02-23T14:00:00"}
details: "blabla",
id: 2830,
}

searchText - is text which inputted by user.

It has to filter data when user inputs text, but it doesn't work because it throws exception(Maximum call stack size exceeded). It normally works if definitely to write what kind of fields you want to use to filter data.

ng-repeat="item in transactions |filter:{amount:searchText}"
like image 498
Kostya Vyrodov Avatar asked Jul 29 '15 17:07

Kostya Vyrodov


1 Answers

I had this same problem with a very simple filter, but I was filtering on an array of objects that had a circular reference. I wasn't making any function calls on the filter - it was just the built-in filter on a simple string.

I had two lists of objects with a many-to-many relationship, and once loading them from a $resouce I had set them each up with a property that was an array of all the objects in the other list with which they had a relationship. I had a list of jobs that tracked its own list of tasks, and a list of tasks with its own sublist of jobs.

for (let job of service.jobs)
{
   job.tasks = service.tasks.filter(t => t.jobid == job.id);
}

for (let task of service.tasks)
{
   task.jobs = service.jobs.filter(j => j.taskid == task.id);
}

(The relationship was a little more complex that this, but this was the heart of it).

I was trying to save cycles by associating them up front just once rather than every digest through the page, but it created a circular loop that only caused a problem once I tried to filter them. I probably could have limited it to filter on the non-"task" fields, but I actually do want to look through them as well. I changed it so that the view just calls the function to pull the related objects inline in the template.

<div ng-repeat="job in service.jobs | filter:jobFilterText">  <-- BOOM
   <div ng-repeat="task in service.getTasksForJob(job.id)">
      {{ task.name }}
   </div>
</div>

The other option I considered was creating a shallow copy of the objects to put in their sub-arrays without the reference back to the original object types, but until I hit a performance problem with the inline binding I prefer its simplicity.

like image 53
Danny Avatar answered Oct 30 '22 17:10

Danny