Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

ngOptions slow in IE with large arrays #12076

Closed
a-b-b-a opened this issue Jun 10, 2015 · 11 comments · Fixed by #14400
Closed

ngOptions slow in IE with large arrays #12076

a-b-b-a opened this issue Jun 10, 2015 · 11 comments · Fixed by #14400

Comments

@a-b-b-a
Copy link

a-b-b-a commented Jun 10, 2015

I have a 500+ element array which I want to bind to a <select> element.
In Chrome, this works fine, adding the array takes a fraction of a second.
In IE, it takes multiple seconds to add the array, during which time the UI is unresponsive.

Looking at timelines, it appears that Chrome recalculates styles after all <option> elements are added, but IE calculates styles and layouts after each <option> is added.

Chrome:
Chrome Timeline
IE:
IE Timeline

Maybe using documentFragments could fix this?

Plunker: http://plnkr.co/edit/ULtEHtcD5La4Ax7hd5kY?p=preview

@wesleycho
Copy link
Contributor

A 500+ element array being bound to a select element sounds like a bad idea from a UX standpoint.

@rebornix
Copy link

rebornix commented Aug 3, 2015

Meeting with the same issue in IE. Per ng-options source code, we know currently Angular is trying to reuse DOM elements to reduce unnecessary DOM redraw.

function addOrReuseElement(parent, current, type, templateElement) {
    var element;
    if (current && lowercase(current.nodeName) === type) {
      element = current;
    } else {
      element = templateElement.cloneNode(false);
      if (!current) {
        // There are no more elements so just append it to the select
        parent.appendChild(element);
      } else {
        parent.insertBefore(element, current);
      }
    }
    return element;
  }

But can we leverage documentFragments when try to append new elements

parent.appendChild(element); // use documentFragments to cache these newly added elements

Then we can avoid the performance hit when select options vastly change. @wesleycho @Narretz pls let me know if this is acceptable.

I tested on my machine with 1000 items in select options, using documentFragment can reduce appendChildren calculation time.

Original code
image

Using DocumentFragment
image

@rebornix
Copy link

rebornix commented Aug 3, 2015

Even if we abandon DOM reuse completely and use documentFragment to recreate the new option list, the performance is still good like below

Update option list from 900 items to 1000 in IE 11.

image

Both deleting option element and appending new options in documentFragment are fast.

@Narretz
Copy link
Contributor

Narretz commented Aug 5, 2015

Can you open a PR that uses documentFragment when appending new elements (without deleting option elements)

@jeffmath
Copy link

I ran into this exact same issue today with IE11. I had to remove my page's dropdowns from Angular's supervision and populate them using JQuery, instead, to get good speed on IE. ngRepeat was a lot faster than ngOptions (~3 seconds vs ~10, respectively) for two dropdowns with ~500 items each, but the JQuery approach takes less than a second. It's a shame to have to wire the dropdowns manually just to be fast on IE.

@seurimas
Copy link

seurimas commented Feb 9, 2016

Hopefully, this can be resolved soon, but here's a hack that defers DOM creation to JQuery for simple lists:

...
      function updateOptions() {
...
        options = ngOptions.getOptions();
        var hackyString = new Array(options.items.length).join("<option value='dumb'>dumb</option>");
        $(selectElement).html(hackyString);
...

This speeds up execution ~100x (2 minutes without versus a little over a second with) for a list 4000 items long. Judging by the path jQuery takes in IE11, generating the list with document fragments is a viable way to go, but I'm not familiar enough to create a real, long-term pull-request to fix.

@jeremysimmons
Copy link

@quantumwannabe solution worked great for me with ie11x64 - 11.0.10586.0
navigator.userAgent = Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
version.exe = windows 10 (10.0.10586)

@Narretz Narretz self-assigned this Apr 9, 2016
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 9, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Always creating new options fixes issues in IE where the select would become unresponsive to user
input.

Fixes angular#13607
Fixes angular#12076
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 9, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Always creating new options fixes issues in IE where the select would become unresponsive to user
input.

Fixes angular#13607
Fixes angular#12076
@Narretz Narretz modified the milestones: 1.5.4, Ice Box Apr 9, 2016
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 11, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Always creating new options fixes issues in IE where the select would become unresponsive to user
input.

Fixes angular#13607
Fixes angular#12076
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 11, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Always creating new options fixes issues in IE where the select would become unresponsive to user
input.

Fixes angular#13607
Fixes angular#13239
Fixes angular#12076
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 12, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Creating new options from scratch fixes issues in IE where the select would become unresponsive
to user input.

Fixes angular#13607
Fixes angular#13239
Fixes angular#12076
Narretz added a commit to Narretz/angular.js that referenced this issue Apr 13, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Creating new options from scratch fixes issues in IE where the select would become unresponsive
to user input.

Fixes angular#13607
Fixes angular#13239
Fixes angular#12076
Narretz added a commit that referenced this issue Apr 13, 2016
This changes the way option elements are generated when the ngOption collection changes.
Previously, we would re-use option elements when possible (updating their text and
label). Now, we first remove all currently displayed options and the create new options for the
collection. The new options are first appended to a documentFragment, which is in the end appended
to the selectElement.

Using documentFragment improves render performance in IE with large option collections
(> 100 elements) considerably.

Creating new options from scratch fixes issues in IE where the select would become unresponsive
to user input.

Fixes #13607
Fixes #13239
Fixes #12076
@scanspeak
Copy link

Thank you for that fix. Rendering of one of my pages with a few fat selects now takes 3 sec on angular 1.5.5 instead of 80 sec on angular 1.5.3. Appreciate it.

@chboing
Copy link

chboing commented Nov 28, 2017

oh yes, thank you !

@kevinlevin123
Copy link

kevinlevin123 commented Mar 9, 2018

Hi,
I'm using Angularjs 1.6 and im having the scenario of loading the table with ng-repeat of approximately 400 rows and within that 400 rows i have dropdown as one of the column. Its working fine in chrome and firefox but its taking much time in internet explorer11 and gets hanged saying long running script. I have used select2.js for dropdown previously but i thought the slowness is because of select2. But even after i removed select2, its still taking the same amount of time with the basic angular select syntax. FYI, ngoptions contains around 30 items inside it.Also Angular 1.6 already using documentFragment to populate select but still its taking much time in IE11. Any thoughts how to improve performance in IE11?

@ramesharige
Copy link

I have the same issues where dropdowns are very slow in IE. I have used the below plunker (http://plnkr.co/edit/ULtEHtcD5La4Ax7hd5kY?p=preview) but got stuck with one more issue.

  1. the model value is not getting updated after the dropdown changed.
    In the change event listener function I have aded the below code. ngModel.$setViewValue(select.options[select.options.selectedIndex].value);
    ngModel.$render();

I checked while debugging got to know that model name is not populating as well. please help on this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.