Skip to content

Commit 155aaad

Browse files
authored
fix: opening menu is slow (#110)
* chore: remove module * chore: update deps * chore: update angular cli * chore: update angular core * fix: virtual scroll * fix: dynamic height * chore: fix broken tests * chore: test loading state * chore: lint * chore: remove impossible test
1 parent 1394406 commit 155aaad

16 files changed

+438
-379
lines changed

.github/workflows/cd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ jobs:
4646
with:
4747
repository-name: BugSplat-Git/bugsplat-git.github.io
4848
branch: gh-pages
49-
folder: dist/ngb-filterable-dropdown-example
49+
folder: dist/ngb-filterable-dropdown-example/browser
5050
target-folder: ngb-filterable-dropdown-example
5151
token: ${{ secrets.GH_TOKEN }}

package-lock.json

Lines changed: 199 additions & 224 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,33 @@
3030
"url": "https://github.com/BugSplat-Git/ngb-filterable-dropdown/issues"
3131
},
3232
"dependencies": {
33-
"@angular/animations": "^19.0.3",
34-
"@angular/common": "^19.0.3",
35-
"@angular/compiler": "^19.0.3",
36-
"@angular/core": "^19.0.3",
37-
"@angular/forms": "^19.0.3",
38-
"@angular/platform-browser": "^19.0.3",
39-
"@angular/platform-browser-dynamic": "^19.0.3",
40-
"@angular/router": "^19.0.3",
41-
"@ng-bootstrap/ng-bootstrap": "^17.0.1",
33+
"@angular/animations": "^19.1.6",
34+
"@angular/cdk": "^19.1.4",
35+
"@angular/common": "^19.1.6",
36+
"@angular/compiler": "^19.1.6",
37+
"@angular/core": "^19.1.6",
38+
"@angular/forms": "^19.1.6",
39+
"@angular/localize": "^19.1.6",
40+
"@angular/platform-browser": "^19.1.6",
41+
"@angular/platform-browser-dynamic": "^19.1.6",
42+
"@angular/router": "^19.1.6",
43+
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
4244
"@popperjs/core": "^2.11.8",
4345
"bootstrap": "^5.3.3",
4446
"rxjs": "^7.8.1",
4547
"tslib": "^2.8.1",
4648
"zone.js": "^0.15.0"
4749
},
4850
"devDependencies": {
49-
"@angular-devkit/build-angular": "^19.1.3",
51+
"@angular-devkit/build-angular": "^19.1.7",
5052
"@angular-eslint/builder": "19.0.1",
5153
"@angular-eslint/eslint-plugin": "19.0.1",
5254
"@angular-eslint/eslint-plugin-template": "19.0.1",
5355
"@angular-eslint/schematics": "19.0.1",
5456
"@angular-eslint/template-parser": "19.0.1",
55-
"@angular/cli": "^19.1.3",
57+
"@angular/cli": "^19.1.7",
5658
"@angular/compiler-cli": "^19.0.3",
57-
"@angular/language-service": "^19.0.3",
59+
"@angular/language-service": "^19.1.6",
5860
"@commitlint/cli": "^19.6.0",
5961
"@commitlint/config-conventional": "^19.6.0",
6062
"@semantic-release/changelog": "^6.0.3",

projects/ngb-filterable-dropdown-example/src/app/app.component.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ <h2>
4949
<label class="ms-4 mb-0" for="disabled">Disabled</label>
5050
</div>
5151
</div>
52+
<div class="row mt-2">
53+
<div class="col-12 col-xl-6">
54+
<input id="loading" (click)="loadingClick($event)" type="checkbox" />
55+
<label class="ms-4 mb-0" for="loading">Loading</label>
56+
</div>
57+
</div>
5258
<div class="row mt-4">
5359
<div class="col-12 col-xl-3">
5460
<label for="selection-mode">Selection Mode</label>
@@ -86,6 +92,7 @@ <h3>Bugs</h3>
8692
[autoClose]="autoClose"
8793
[items]="items"
8894
[disabled]="disabled"
95+
[loading]="loading"
8996
[searchInputPlaceholder]="searchInputPlaceholder"
9097
[selection]="selection"
9198
[selectionMode]="selectionMode"
@@ -103,6 +110,7 @@ <h3>Bugs</h3>
103110
[autoClose]="autoClose"
104111
[items]="items"
105112
[disabled]="disabled"
113+
[loading]="loading"
106114
[placeholder]="'No Bugs Selected'"
107115
[searchInputPlaceholder]="searchInputPlaceholder"
108116
[selection]="selection"
@@ -116,13 +124,35 @@ <h3>Bugs</h3>
116124
</div>
117125
</div>
118126
<hr />
127+
<div class="row mt-4">
128+
<div class="col-12 col-xl-6">
129+
<h3>Lots and Lots of Items</h3>
130+
<ngb-filterable-dropdown
131+
[allowCreateItem]="allowCreateItem"
132+
[autoClose]="autoClose"
133+
[disabled]="disabled"
134+
[items]="lotsOfItems"
135+
[loading]="loading"
136+
[searchInputPlaceholder]="searchInputPlaceholder"
137+
[selection]="lotsOfItemsSelection"
138+
[selectionMode]="selectionMode"
139+
[tooltips]="tooltips"
140+
[tooltipsOpenDelay]="tooltipsOpenDelay"
141+
(itemCreated)="onItemCreated($event)"
142+
(selectionChanged)="lotsOfItemsSelectionChanged($event)"
143+
>
144+
</ngb-filterable-dropdown>
145+
</div>
146+
</div>
119147
<div class="row mt-4">
120148
<div class="col-12 col-xl-6">
121149
<h3>Custom Click Handle</h3>
122150
<ngb-custom-filterable-dropdown
123151
[allowCreateItem]="allowCreateItem"
124152
[autoClose]="autoClose"
153+
[disabled]="disabled"
125154
[items]="items"
155+
[loading]="loading"
126156
[searchInputPlaceholder]="searchInputPlaceholder"
127157
[selection]="genericHandleSelection"
128158
[selectionMode]="selectionMode"
@@ -145,7 +175,9 @@ <h3>Styled Custom Click Handle</h3>
145175
<ngb-custom-filterable-dropdown
146176
[allowCreateItem]="allowCreateItem"
147177
[autoClose]="autoClose"
178+
[disabled]="disabled"
148179
[items]="items"
180+
[loading]="loading"
149181
[searchInputPlaceholder]="searchInputPlaceholder"
150182
[selection]="genericHandleSelection"
151183
[selectionMode]="selectionMode"

projects/ngb-filterable-dropdown-example/src/app/app.component.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@
33
padding: 15px;
44
min-height: 1200px;
55
}
6+
7+
.alert.alert-dark {
8+
overflow: hidden;
9+
text-overflow: ellipsis;
10+
}

projects/ngb-filterable-dropdown-example/src/app/app.component.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { TestBed } from "@angular/core/testing";
22
import {
3-
NgbCustomFilterableDropdownModule,
4-
NgbFilterableDropdownModule,
3+
NgbCustomFilterableDropdownComponent,
4+
NgbFilterableDropdownComponent,
55
} from "projects/ngb-filterable-dropdown/src";
66
import { AppComponent } from "./app.component";
77

@@ -10,8 +10,8 @@ describe("AppComponent", () => {
1010
await TestBed.configureTestingModule({
1111
imports: [
1212
AppComponent,
13-
NgbCustomFilterableDropdownModule,
14-
NgbFilterableDropdownModule,
13+
NgbCustomFilterableDropdownComponent,
14+
NgbFilterableDropdownComponent,
1515
],
1616
}).compileComponents();
1717
});

projects/ngb-filterable-dropdown-example/src/app/app.component.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { CommonModule } from "@angular/common";
22
import { Component } from "@angular/core";
33
import {
44
ItemCreatedEvent,
5-
NgbCustomFilterableDropdownModule,
6-
NgbFilterableDropdownModule,
5+
NgbCustomFilterableDropdownComponent,
6+
NgbFilterableDropdownComponent,
77
NgbFilterableDropdownSelectionMode,
88
OpenChangedEvent,
99
SelectionChangedEvent,
@@ -14,8 +14,8 @@ import {
1414
templateUrl: "./app.component.html",
1515
styleUrls: ["./app.component.scss"],
1616
imports: [
17-
NgbFilterableDropdownModule,
18-
NgbCustomFilterableDropdownModule,
17+
NgbFilterableDropdownComponent,
18+
NgbCustomFilterableDropdownComponent,
1919
CommonModule,
2020
],
2121
})
@@ -34,7 +34,12 @@ export class AppComponent {
3434
"Fire Ant",
3535
"Dung Beetle",
3636
"Grass Ant",
37-
"A Really Long Made Up Bug Name For Testing Tooltips Etc Etc Yadda Yadda Yadda",
37+
"A Really Long Made Up Bug Name For Testing Tooltips Etc Etc Yadda Yadda Yadda",
38+
];
39+
40+
lotsOfItems = [
41+
...this.items,
42+
...this.generateLotsOfItems(),
3843
];
3944

4045
allowCreateItem = false;
@@ -44,11 +49,13 @@ export class AppComponent {
4449
genericHandleUseCustomHandle = true;
4550
genericHandleSelection: string | Array<string> = "nothing";
4651
isGenericHandleDropdownOpen = false;
52+
lotsOfItemsSelection: string | Array<string> = "";
4753
searchInputPlaceholder = "Search Bugs";
4854
selection: string | Array<string> = "Moth";
4955
selectionMode = NgbFilterableDropdownSelectionMode.SingleSelect;
5056
tooltips = false;
5157
tooltipsOpenDelay = 750;
58+
loading = false;
5259

5360
allowCreateItemClick(event: CheckboxClickEvent): void {
5461
this.allowCreateItem = event.target.checked;
@@ -71,6 +78,10 @@ export class AppComponent {
7178
this.genericHandleSelection = $event.selection;
7279
}
7380

81+
lotsOfItemsSelectionChanged($event: SelectionChangedEvent): void {
82+
this.lotsOfItemsSelection = $event.selection;
83+
}
84+
7485
onAutoCloseValueChanged(value: boolean | "inside" | "outside"): void {
7586
this.autoClose = value;
7687
}
@@ -98,6 +109,14 @@ export class AppComponent {
98109
tooltipsClick(event: CheckboxClickEvent): void {
99110
this.tooltips = event.target.checked;
100111
}
112+
113+
loadingClick(event: CheckboxClickEvent): void {
114+
this.loading = event.target.checked;
115+
}
116+
117+
private generateLotsOfItems(): Array<string> {
118+
return Array.from({ length: 100000 }, (_, i) => `Bug ${i}`);
119+
}
101120
}
102121

103122
interface CheckboxClickEvent {

projects/ngb-filterable-dropdown/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"peerDependencies": {
1717
"@angular/common": ">=19.0.0",
1818
"@angular/core": ">=19.0.0",
19+
"@angular/cdk": ">=19.0.0",
1920
"@ng-bootstrap/ng-bootstrap": ">=18.0.0",
2021
"bootstrap": ">=5.3.3"
2122
}

projects/ngb-filterable-dropdown/src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@
33
*/
44

55
export * from './lib/ngb-custom-filterable-dropdown/ngb-custom-filterable-dropdown.component';
6-
export * from './lib/ngb-custom-filterable-dropdown/ngb-custom-filterable-dropdown.module';
76
export * from './lib/ngb-filterable-dropdown/ngb-filterable-dropdown.component';
8-
export * from './lib/ngb-filterable-dropdown/ngb-filterable-dropdown.module';
97
export { ItemCreatedEvent, SelectionChangedEvent, OpenChangedEvent } from './lib/events';

projects/ngb-filterable-dropdown/src/lib/ngb-custom-filterable-dropdown/ngb-custom-filterable-dropdown.component.html

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,6 @@
6868
<icon-plus></icon-plus>
6969
Create {{ searchInputValue }}
7070
</button>
71-
<div *ngFor="let item of items" [hidden]="loading">
72-
<button
73-
class="dropdown-item filterable-dropdown-item px-2"
74-
type="button"
75-
[ngbTooltip]="item"
76-
[disableTooltip]="!tooltips"
77-
[openDelay]="tooltipsOpenDelay"
78-
[hidden]="!isFiltered(item)"
79-
(click)="onItemSelect(item)"
80-
>
81-
<div class="d-flex flex-row">
82-
<div class="item-text-container">{{ item }}</div>
83-
<div class="w-100 text-end" [hidden]="!isSelected(item)">
84-
<icon-checkmark></icon-checkmark>
85-
</div>
86-
</div>
87-
</button>
88-
</div>
8971
<div [hidden]="!noItemsToDisplay" id="no-items" class="dropdown-item">
9072
No items to display.
9173
</div>
@@ -99,6 +81,31 @@
9981
<div [hidden]="!loading" id="loading" class="dropdown-item">
10082
Loading...
10183
</div>
84+
<cdk-virtual-scroll-viewport
85+
#viewport
86+
[itemSize]="ITEM_SIZE"
87+
class="virtual-scroll-viewport"
88+
[hidden]="!filteredItems.length || loading"
89+
[style.height.px]="viewportHeight"
90+
>
91+
<div *cdkVirtualFor="let item of filteredItems">
92+
<button
93+
class="dropdown-item filterable-dropdown-item px-2"
94+
type="button"
95+
[ngbTooltip]="item"
96+
[disableTooltip]="!tooltips"
97+
[openDelay]="tooltipsOpenDelay"
98+
(click)="onItemSelect(item)"
99+
>
100+
<div class="d-flex flex-row">
101+
<div class="item-text-container">{{ item }}</div>
102+
<div class="w-100 text-end" [hidden]="!isSelected(item)">
103+
<icon-checkmark></icon-checkmark>
104+
</div>
105+
</div>
106+
</button>
107+
</div>
108+
</cdk-virtual-scroll-viewport>
102109
</div>
103110
</div>
104111
</div>

0 commit comments

Comments
 (0)