-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MdSelect and MdAutocomplete slow initial render w/ large number of options #5113
Comments
@crisbeto I think we should tackle this the same way we're dealing with tabs- to add an additional API where the options are in an |
Makes sense, I'll see what I can do. |
@jelbourn I did some exploration into it. The problem with using an |
We could add an extra API to the trigger for that case; the trade-off ends up being simplicity vs performance |
We do have the |
Thinking about it more, perhaps we need to go the route we took with the table here. Something like <mat-select-trigger [panel]="panel">
{{panel.selectedOption.name}}
</mat-select-trigger>
<mat-select-panel #panel [dataSource]="myOptions">
<mat-option *matOptionDef="let option; when">{{option.name}}</mat-option>
</mat-select-panel> It's a pretty dramatic departure from the current API- maybe we consider this for the next major release and instead say that lazily instantiated option-lists need to be explicitly given trigger text. |
An alternative approach can be to hand over all rendering to Material. e.g. the user provides the data source and a function that determines what the output should look like: <mat-select [options]="arrayOfOptions" [displayWith]="functionThatReturnsAString"></mat-select> |
The issue there is that you lose the ability to custom-template the options. Even with the datasource approach you lose the ability to control how the options are expanded declaratively, but that might be a reasonable trade-off (we decided it was necessary for the table so it could have control over scrolling) |
I have such error for every item in mat-select
This #4221 (comment) helps, and the performance is much better (I have 900 items list) |
Any update on this? |
I'm running into this same issue with Select and cannot find a workaround. If I have 100s of select options the view hangs on load (setting values in onInit). Anyone found a workaround? |
@timharris777 I've worked around it by incrementally searching and loading a subset of the data. Code: https://github.com/OasisDigital/angular-material-obs-autocomplete demo: https://oasisdigital.github.io/angular-material-obs-autocomplete/ What I like about this code: it works, yields a decent user experience, today. What I don't like about it: It doesn't "fix" the problem so much as avoided by implementing a different set of features, and it requires more work and understanding behind the scenes. See demo and demo code. |
In IE / EDGE if I have a high number of mat-selects on a page, the opening of one of them is very slow. This happens if I have only one option too. Can anyone help me? Angular 6.1.2 with material 5 this not happen !!! |
@swftvsn I've been working with some MdSelect and MdAutocomplete elements that have large lists (sometimes can reach 25.000 items), and they both become extremely slow (both for opening and searching through them). |
As suggested by crisbeto this is giving me error. Can't bind to 'options' since it isn't a known property of 'mat-select'. |
Lazy loading could have other benefits. For example I'm facing when I have: <mat-form-field>
<mat-label>{{ type }}</mat-label>
<mat-autocomplete #autocomplete>
<mat-option *ngFor="let option of obsThatMakesHttpRequest | async">
{{ option.DisplayName }}
</mat-option>
</mat-autocomplete>
<input matInput [matAutocomplete]="autocomplete" />
</mat-form-field> 50 times, makes 50 request immediately, rather then one by one when you interact with them. |
This is my work around <mat-form-field>
<mat-label>{{ type }}</mat-label>
<mat-autocomplete #autocomplete>
<ng-template [ngIf]="autocomplete.isOpen">
<mat-option *ngFor="let option of obsThatMakesHttpRequest | async">
{{ option.DisplayName }}
</mat-option>
</ng-template>
</mat-autocomplete>
<input matInput [matAutocomplete]="autocomplete" />
</mat-form-field> |
Any news on this? |
This is so slow in development, I switched to react along with material-UI for my new project. It offers highly advanced multi-select menus by default no third-party components are needed. I won't recommend anybody using angular material, it's very slow in development. I got fooled by the 'Angular' keyword like its official UI for angular. |
+1 |
As @jelbourn mentioned before, fixing this in Angular Material would require a breaking API change, but for really bad cases with lots of import {
Pipe,
PipeTransform,
OnDestroy,
ChangeDetectorRef,
} from '@angular/core';
import { MatSelect } from '@angular/material/select';
import { Subscription } from 'rxjs';
/**
* Initializes only the selected `<mat-option>`s to remove the up-front cost of
* initializing and rendering off-DOM all of the select options, which can
* number in thousands and make initial page rendering slow.
*/
@Pipe({ name: 'lazyOptions', pure: false })
export class LazyOptionsPipe implements PipeTransform, OnDestroy {
private selectedOptionsOnly = true;
private subscription: Subscription;
constructor(
private readonly select: MatSelect,
private readonly cdr: ChangeDetectorRef
) {
this.subscription = this.select.openedChange.subscribe(() => {
this.selectedOptionsOnly = false;
});
// Preload after some time.
requestIdleCallback(
() => {
this.selectedOptionsOnly = false;
this.cdr.markForCheck();
},
{ timeout: 1000 }
);
}
transform<T>(values: T[]): T[] {
if (!this.selectedOptionsOnly) {
return values;
}
return values.filter((value) => {
return this.select.compareWith(value, this.select.value);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
} To use, just specify it in your template: <mat-form-field appearance="fill">
<mat-label>Select an option</mat-label>
<mat-select [(value)]="selected">
<mat-option>None</mat-option>
<mat-option *ngFor="let value of values | lazyOptions" [value]="value"
>{{value}}</mat-option
>
</mat-select>
</mat-form-field> |
Bump. |
For both
MdSelect
andMdAutocomplete
, the initial render of the component (in the closed state) is very slow even though the panels are closed. We should ensure that any work related to the options is deferred until the panel is opened.To reproduce this, simply modify the demos to render 500
md-select
each with 500 options each (there is no problem if there are 500 selects with 1 option each).The text was updated successfully, but these errors were encountered: