ui-select
ui-select copied to clipboard
big array performance issue
Hi, I have form for customer information, with three fields which use ui-select, every is for selecting country (country array length is 251) when countries array is loaded for ui-select it causes some lag on the page with this data, I've saw that there are some issues open with pagination for far future so now I can resolve my problem by adding checking for minimum input length for example 3 characters, than pagination is made on backend, but when customer is loaded with such information like $scope.customer.country_id I need to load all countries before, so solution with minium input length for 3 characters can't be applied in that case. Some ideas how to achieve that? I was trying to reduce watchers by adding :: to ui-select's expressions (one time binding - Angular 1.3 feauture) but with no result.
You could virtualize the list, only rendering DOM that are in view.
@amcdnl can you expand your idea? Now my script for counting watchers on the page is showing 3163 watchers (2 fields with ui-select and list of countries) so too too much.
UPDATE: I've reduced by 2000 watchers after remove datepicker from angular-ui packet.
I could use an answer for this. I'm not sure how to proceed with a list of 14k in my dropdown. I wanted to use minLength but that's not implemented yet.
@simkessy I've implemented min length in my project, and limit with result, you can check related issue : https://github.com/angular-ui/ui-select/issues/274#issuecomment-63368278 where I wrote solution for this. Here you can check how I resolved limit for result : https://gist.github.com/masscrx/3a9ba4b3df4cdd7012ea and in html you can add something like this then:
<ui-select-choices limit="10" refresh="checkCountry($select.search)" refresh-delay="500" repeat="country as country in countries | filter: $select.search">
This is my workaround for big array till guys make some official functions for this ;-)
@masscrx sorry for the delay, busy week.
Virtualizing a list means only the viewable items are rendered in the dom. The other items may be in memory or paged at the server level when came into view.
Heres an example ( would not recommend trying with our select though ) but gives the idea: https://github.com/kamilkp/angular-vs-repeat
Tagging as an enhancement; PR's welcome if you want to contribute.
this would be huge. I would not mind working on it at some point but that would require me to not be busy... so not any time soon I think
+1
What about virtual dom like react type implementation?
Interesting that might do the trick. With a react style dom we could have the list already built and merely injected when the ui-select dropdown opens.
On a related note I did notice we have a lot of slowdowns that just come from "ng-if/show"s that are calling a function. I think those have to call every cycle right?
I also noticed ng-if slows ui-select down when it gets opened, but after quick profiling I found that it's because of ngAnimate, that by default "animates" every ng-if, ng-show, etc. (a lot of requestAnimationFrame calls). When I turned-off ngAnimate for ui-select it became 2x faster.
But this is only if you use ngAnimate, of course.
If this PR https://github.com/angular-ui/ui-select/pull/430 could get merged in it would probably solve a lot of the issues as well by limiting the DOM size.
Any word on virtualizing? This is something that's come up for us as well.
I have not done anything with it. infinite scrolling may still be the best bet and if not that then #430
@Anton-Rodionov How did you turn off ngAnimate on the ui-select. I, too, am getting rAF calls for every item in the list, which slows it down considerably.
Also interested in turning off ngAnimate effect on the ui-select component, while keeping it working for other components.
+1
You guys might find some inspiration from here; https://github.com/select2/select2/issues/781 — since Select2 guys were having similar problems.
+1
+1
I have had recent success with infinite scroll using this library. http://binarymuse.github.io/ngInfiniteScroll/ it is a bit more work, but if you only have a few big lists then this is decent work around.
@dmccown1500 could you post a demo of what you did?
Hey sorry did not have a ton of time, but I threw together a plunker. It is not quite working right (no idea why seems like the same thing I did on our webapp) but should at least give you some direction: http://plnkr.co/edit/OwhFCyHz0mO1yZMj5UW5?p=preview
Update ok I got it working now: http://plnkr.co/edit/OwhFCyHz0mO1yZMj5UW5?p=preview I realized we were using a modified version of the library. pretty small change but it was slightly different. All credit to the ng-infinite-scroll team for the bulk of the code
@dmccown1500 thank you!! your plunker is very helpful :)
@twrk glad to hear is was helpful. I love this library and would really like to see something like this get pulled in natively.
@dmccown1500 thank you too!! it's magic!
@dmccown1500 +10 cool stuff.
@twrk +1 making native this code
@dmccown1500 I both the infinitescroll and the #430 are needed.
@jpdesigndev A bit about how to turn ngAnimate. Every item of the list that ui-select renders is wrapped by ng-show. By default, every ng-show is animated (it might be not a real animation, but ng-enter, ng-leave, etc. classes still get added). That's what brings slowness. To avoid that you could define a regexp to animate only the elements you want.
.config(['$animateProvider', function($animateProvider) {
// Setup `ngAnimate` to work only with angular-motion classes (`am-` prefixed)
// or custom animation classes (`animate-` prefixed) to boost performance
$animateProvider.classNameFilter(/(animate|am)-/);
}])