22

I have a problem with angular ng-repeat directive. Currently I work on some project where from the API I get a list of items (some times it could be 1k items) and this list should be refreshed every 5 seconds (it is monitoring related project).

When the list length is a little bigger the website while re-rendering DOM could "slow". It comes out that angular regenerate the whole DOM (but 95% of item are the same ! )

One of the possible approach is to set "track by" expression for example to item.id. But here comes another problem, I also want regenerate items when for example descriptions was changed by other user. Since track by is expression to item.id changes in item.description didn't update item in DOM.

There is way to track by over multiple properties? Maybe some function? Or maybe do comparison by "hand" ?

Any ideas, code samples I would appreciate :)

UPDATE

what I discover when I set track by to item.id angular didn't re-crete html for items, just update value in already created element and it seems to be "faster" then removing and creating. Previously I though a little bit different.

FIX

For those who are looking for better performance over >1k items in ng-repeat USE track by item.id it will boost your performance ;)

qwetty
  • 1,145
  • 1
  • 9
  • 23
  • 2
    You can use a function like `track by tracker(item)`, where `tracker()` is a function visible in the scope of the repetition. Then again the "slowness" may also be caused by having the view create thousands of watches (e.g. 1k rows, three properties per row = 3000 watches). You may need to identify the problem more precisely and/or rethink some details. – Nikos Paraskevopoulos Jan 30 '15 at 09:09
  • And the watches will fire even though the `track by` does not repaint any rows of your DOM. – Nikos Paraskevopoulos Jan 30 '15 at 09:10
  • What would be faster: whole DOM regenerating or manually comparing items? – qwetty Jan 30 '15 at 09:30
  • I really don't know and I doubt if all cases can be covered by one answer. Profile and see, I guess :) Oh, and another "trick" would be to limit the created DOM and the watches to only what is visible by the user. – Nikos Paraskevopoulos Jan 30 '15 at 12:01

3 Answers3

39

You do not need to create a function to handle track by multi properties. You can do:

<div ng-repeat="item in lines track by item.id+item.description">
Pedro Justo
  • 3,319
  • 1
  • 13
  • 21
23

As the comment suggested you could try something like this:

<select ng-model="item" ng-options="item.id as item.description for item in items track by itemTracker(item)">

In your controller:

$scope.itemTracker= function(item) {
  return item.id + '-' + item.description;
}

This might help with the number of DOM elements being re-rendered when the list changes.

Wawy
  • 6,201
  • 2
  • 20
  • 23
  • 1
    I like this approach but you should note that if both fields are numeric you could generate conflicting values. For example: if `item.id = 5` and a possible `item.code = 2` it would generate the same tracker value for an `item.id = 6` and `item.code = 1`. I solved this by returning `'['+item.id+']'+'['+item.code+']'` so it would generate a unique tag for the tracker to compare – Netherdan Oct 09 '18 at 15:24
0

Based my knowledge, the angularjs model is bind to the ui view, so the model will rerender via $apply or $digest once the value changed. so in your case, u wan bind the model value to ui view but also do not want to re-render the view if the value has not change,that is impossbile. this is what i know.

however, u can just manipulate the dom element. for example store the data to a variable

var x = [{id:"id1",value:"v1"},{id:"id2",value:"v2"}]

in html, manual append or using directive to append, then assign the id to the element,

<div id="id1">v1</div>

check and compare the value, based ur needs. once found, then angular.element("#yourid").text()

this will solve your browser resources consume problems.

Stupidfrog
  • 1,799
  • 5
  • 22
  • 33
  • This seems like a very un-Angular approach, but perhaps I am not understanding your suggestion. Can you explain how this approach gives the OP's ng-repeat tracking on 2 properties and how this will effect performance? – Gary Aug 08 '16 at 15:40