Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: virtual repeat with row with different heights

I'm building an hybrid app using ionic and AngularJS (AngularJS-material). This app also has an integrated chat built with Node.js and socket.io.

I have the problem now that with only 200 messages the app gets very slow to load all the messages (200ms in Browser -> 4sec in app, even with CrossWalk, and with track by message.id) and also typing in the the textarea to insert the message is slowed down.

I have two solutions to resolve this:

  1. Virtual Repeat (md-virtual-repeat)
  2. Infinite Scroll (ion-infinite-scroll)

1) I think that virtual repeat would be the best solution (I have already implemented it on another page and it scrolls 1500 items like a charm) but the problem is that the messages can have different heights based on their lenghts and md-virtual-repeat requirements are that all the elements must have the same height to work.

2) So maybe we can pivot to the Infinite Scroll method but the problem now is that doing it with the ion-infinite-scroll directive gets a bit tricky since a chat needs to trigger the loadMore() when reaching the top and not the bottom.

So my question is: Does anybody have a workaround to have a smooth/fast ng-repeat inside a chat using or a virtual-repeat directive that can handle different heights or an infinite scroll that works at the top ?

like image 654
Matteo Cardellini Avatar asked Dec 30 '15 23:12

Matteo Cardellini


2 Answers

Efficient scroll lists like md-virtual-repeat or collection-repeat need to know the height of each item in order to work. That’s because they need to know the scroll position, e.g. to show a scrollbar or to be able to skip frames for quick swipe-down motions. The scroll position itself can only be found if you know both how much has been scrolled (we need the height of elements above) and how much there is left to scroll (we need the height of elements below).

What you can do is use a factory to compute the height of each element before injecting them into the loop. This can be done by creating a container with the same properties as the target container (e.g. CSS classes), appending the newly-loaded elements, compute their height (using element.offsetHeight), and removing the container after.

Be aware that this is quite heavy and will likely cause a small lag spike.

like image 66
Iso Avatar answered Nov 01 '22 12:11

Iso


Couple of things you could try to speed it up.

One would be to use something like quick-ng-repeat: https://github.com/allaud/quick-ng-repeat instead of built in angular js ng-repeat

Another would be to use one time binding where ever possible to prevent angular from constantly looking for changes during every digest cycle: https://docs.angularjs.org/guide/expression#one-time-binding

And of course, if it's possible, try using chrome's developer tool profile option to find out which of the functions are slowing the application down ; )

PS: Might be worth checking out this thread to see how reverse infinite scrolling could be implemented: Implementing a reverse infinite scroll using ngInfiniteScroll directive in AngularJS

like image 2
Chanthu Avatar answered Nov 01 '22 12:11

Chanthu