angular-ui / ui-select

AngularJS-native version of Select2 and Selectize
MIT License
3.26k stars 1.81k forks source link

big array performance issue #389

Open masscrx opened 9 years ago

masscrx commented 9 years ago

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.

amcdnl commented 9 years ago

You could virtualize the list, only rendering DOM that are in view.

masscrx commented 9 years ago

@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.

simkessy commented 9 years ago

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.

masscrx commented 9 years ago

@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 ;-)

amcdnl commented 9 years ago

@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

amcdnl commented 9 years ago

Tagging as an enhancement; PR's welcome if you want to contribute.

dmccown1500 commented 9 years ago

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

maxisam commented 9 years ago

+1

amcdnl commented 9 years ago

What about virtual dom like react type implementation?

dmccown1500 commented 9 years ago

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?

Anton-Rodionov commented 9 years ago

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.

dmccown1500 commented 9 years ago

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.

seiyria commented 9 years ago

Any word on virtualizing? This is something that's come up for us as well.

dmccown1500 commented 9 years ago

I have not done anything with it. infinite scrolling may still be the best bet and if not that then #430

paynecodes commented 9 years ago

@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.

dorrotman commented 9 years ago

Also interested in turning off ngAnimate effect on the ui-select component, while keeping it working for other components.

yaring commented 9 years ago

+1

simison commented 9 years ago

You guys might find some inspiration from here; https://github.com/select2/select2/issues/781 — since Select2 guys were having similar problems.

ahuang321 commented 9 years ago

+1

igorlino commented 9 years ago

+1

dmccown1500 commented 9 years ago

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.

simkessy commented 9 years ago

@dmccown1500 could you post a demo of what you did?

dmccown1500 commented 9 years ago

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

dmccown1500 commented 9 years ago

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

tw-zz-rk commented 9 years ago

@dmccown1500 thank you!! your plunker is very helpful :)

dmccown1500 commented 9 years ago

@twrk glad to hear is was helpful. I love this library and would really like to see something like this get pulled in natively.

dometec commented 9 years ago

@dmccown1500 thank you too!! it's magic!

igorlino commented 9 years ago

@dmccown1500 +10 cool stuff.

@twrk +1 making native this code

igorlino commented 9 years ago

@dmccown1500 I both the infinitescroll and the #430 are needed.

Anton-Rodionov commented 9 years ago

@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)-/);
}])
dmccown1500 commented 9 years ago

Anton, that is a really interesting idea. And it would be kind of nice in that it enforces the naming convention internally for animation classes. That said for library heavy apps it seems like it would cause a lot of animations in the libraries to not work. Thanks for the idea!

paynecodes commented 9 years ago

@Anton-Rodionov Thanks for the detailed explanation. This is exactly what I ended up doing. I'm still curious if there is a way to handle this for certain modules instead of app-wide. In any case, I got it working just as you showed. Thanks for leading me down the right track.

hopewise commented 9 years ago

how to turn ngAnimate off for all items of ui-select from inside the scope of where its been used?

Anton-Rodionov commented 9 years ago

@jpdesigndev @hopewise To restrict ngAnimate to the certain scope instead of whole application you could try ng-animate-children="false" directive.

hopewise commented 9 years ago

thanks, but it still very slow, I wonder how this custom-select https://github.com/axel-zarate/js-custom-select is very speedy comparing to select-ui

simison commented 9 years ago

@hopewise I switched to Angular-Chosen, a bit more established than js-custom-select.

hopewise commented 9 years ago

thanks for the link, I will check it right away..

raphaklaus commented 9 years ago

@hopewise, I've checked this one, but unfortunately it depends on jQuery.

estvmachine commented 9 years ago

Vote for a native version of ui-select with ng-infinite-scroll like suggested @dmccown1500, thanks your plunker works

hyzhak commented 9 years ago

@estvmachine https://github.com/hyzhak/ui-select-infinity thy this extension for ui-select. If it won't work to you feel free add issue or PR.

iamdey commented 9 years ago

solving #221 could help here

andrewboni commented 9 years ago

@dmccown1500 thanks for that snippet- helpful. Any thoughts on why it breaks when using theme="selectize"?. See example plunkr here: http://plnkr.co/edit/cvOlgWaoBmvwoRrtY8XX?p=preview

R4GN4R0KX commented 9 years ago

@dmccown1500 thanks but the infinity extension disables the search

brenovieira commented 9 years ago

@dmccown1500, @simison, @amcdnl

Yesterday I took a look at infinite scroll, and it "solves" my problem.

I have an array of at least 2.000 complex objects, so I was using limitTo : 30, but pre-selecting was broke. Now with infinite scroll seems to work fine, fast and pre-select works.

But here is my concern, now: As I just added jQuery to use infinite scroll, I'm thinking what is the advantage of using ui-select over angular chosen.

The feature I need is just a field to select multi options (multi select).

What do you guys think ?

dmccown1500 commented 9 years ago

@brenovieira So our team used angular-chosen for a while and while it works reasonably well it seemed to have more issues with Angular proper and would occasionally not update correctly or have odd view problems when ng-show/ng-hide. If you did not have a jQuery dependency before I would think carefully if the infinite scroll solution is the right way to go, on the other hand almost inevitably you will eventually have a jQuery dependency on a large project so maybe it is ok.

brenovieira commented 9 years ago

Thanks @dmccown1500

I didn't know angular chosen was kind of "buggy". When I searched for a lib to solve my multi select need some months ago, I thought ui-select was the right choice.

But now I don't know what to do, because ui-select has

Yesterday I looked all open issues and I think these two are the biggest issues with ui-select right now and my app has both hahaha

I really don't wanna add jQuery, since I'm building a chrome extension that just needs a multi select datepicker and a multi select field to select airports. Then the extension fetches flights for multi origins, destinations, departure and return dates. So its ui isn't a large project with many dependencies (it's quite simple).

What do you think @dimirc, @cdjackson, @ProLoser ? Please, let me know if I can help with these two issues.

ProLoser commented 9 years ago

@brenovieira use a normal datepicker and just every time a selection is made, push to an array. I don't know why you're bothering with any other select widget.

dmccown1500 commented 9 years ago

@brenovieira I would agree with @ProLoser this is way overkill for what you are trying to accomplish

brenovieira commented 9 years ago

@ProLoser, @dmccown1500, the datepicker need is already addressed.

Now I just need a field to select multi values that works fast with +2k items hahaha

Note: I just mentioned datepicker to show it's a "simple" application. Note2: I can't use normal datepicker and $watch changes, because the datepicker doesn't show all selected dates and I need range selection as well.

I'm sorry for the confusion, but they're separated components on my app:

extension

The datepicker works just fine after I made some PR.

But ui-select isn't ready for production in my case, because I have two ui-select. each has +2k complex items (all airports in the world) hehehhe

Did you get it now ?

dmccown1500 commented 9 years ago

@brenovieira Ahh ok I see what you are trying to do now. So just thinking out loud here but Angular material has the idea of virtual scroll which might work with their chips, but it is tied to their library so that is probably a non-starter... https://material.angularjs.org/latest/demo/virtualRepeat