Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS 'ng-filter' is very slow on array of ~1000 elements

I have a simple <input> search filter set up for a list of itemnames in AngularJS.

My list looks like this:

var uniqueLists = {     category1: ['item1', 'item2', 'item3' ... 'item180' ], // Real list contains ~180 items     category2: ['itemA', 'itemB', 'itemC' ... 'itemZZZ' ], // Real list contains ~1080 items     category3: ['otheritem1', 'otheritem2', 'otheritem3' ]  // Real list contains 6 items   } 

I iterate through this list in Angular and print out the results in a <ul> for each category.

<div ng-repeat="(key,val) in uniqueLists">     <form ng-model="uniqueLists[index][0]">         <input ng-model="searchFilter" type="text" />             <ul>                 <li ng-repeat="value in val | filter: searchFilter">                     <label>                          <input type="checkbox" ng-model="selectedData[key][value]" />                         {{value}}                     </label>                 </li>             </ul>     </form> </div> 

For clarity, selectedData looks like this:

var selectedData = {category1: [item1:true], category2: [], category3: []); // if 'item1's checkbox is checked. 

This list is working just fine, although the filter is quite laggy, even on my quite-fast computer. Typing a letter into the input takes 1-2 seconds for the list to update.

I'm aware that this is likely because I'm filtering through around about 1000 items at a time, but I haven't seen any discussion of this elsewhere.

Is there any way to get better performance out of the filter?

like image 444
JVG Avatar asked Jul 31 '13 11:07

JVG


People also ask

What is correct way to apply multiple filters in AngularJS?

Filters can be applied to the result of another filter. This is called "chaining" and uses the following syntax: {{ expression | filter1 | filter2 | ... }} E.g. the markup {{ 1234 | number:2 }} formats the number 1234 with 2 decimal points using the number filter.

What does the AngularJS filter filter do?

The “filter” Filter in AngularJS is used to filter the array and object elements and return the filtered items. In other words, this filter selects a subset (a smaller array containing elements that meet the filter criteria) of an array from the original array.

Can we use filter in NG model?

The ng-repeat values can be filtered according to the ng-model in AngularJS by using the value of the input field as an expression in a filter. We can set the ng-model directive on an input field to filter ng-repeat values. The below illustrations describes the approach for the implementation.


2 Answers

The main problem with the filter approach is that upon each change the dom is manipulated, so it's not the filter that's slow but the consequences. An alternative is to use something like:

ng-show="([item] | filter:searchFilter).length > 0" 

on the repeated element.

Lending some code from @OverZealous, you can use the following to compare the behaviour:

  • filter: http://jsbin.com/fuwadanu/1/
  • ng-show: http://jsbin.com/xajehulo/1/

Update: With Angular v1.2 came the track by syntax. Which also helps with such problems. Provided the elements have some unique attribute, one can use:

ng-repeat="item in items | filter:searchFilter track by item.id" 

Where item.id has to be unique across all items. With track by only those dom-elements will be removed which are no longer the in the final list, others will be remembered. Whereas without track by the whole list is redrawn everytime. In short: much less dom manipulation = quicker redraw.

  • track by: http://jsbin.com/dufasego/1/
like image 141
Yoshi Avatar answered Oct 11 '22 20:10

Yoshi


Another interesting optimization is to 'not trigger' the model change until a certain time.

Adding this to your search input field: ng-model-options="{debounce: 500}"

This will trigger the filter if the user stop typing during 500ms.

I updated the above fiddle:

http://jsfiddle.net/CXBN4/14/

<input ng-model="searchFilter" type="text" ng-model-options="{debounce: 500}" /> 
like image 35
Tyvain Avatar answered Oct 11 '22 22:10

Tyvain