Skip to content

Commit 8cab60a

Browse files
committed
feat(esf): add initial 'load on demand' POC #5448
1 parent 03daa14 commit 8cab60a

13 files changed

+306
-23
lines changed

projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.html

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,33 @@
1919
</igx-icon>
2020
</igx-input-group>
2121

22-
<igx-list [displayDensity]="displayDensity" [style.height.px]="250">
23-
<div [style.overflow]="'hidden'" [style.position]="'relative'">
24-
<igx-list-item
25-
*igxFor="let item of data | excelStyleSearchFilter: searchValue; scrollOrientation : 'vertical'; containerSize: '250px'; itemSize: itemSize">
26-
<igx-checkbox
27-
[value]="item"
28-
tabindex="-1"
29-
[checked]="item.isSelected"
30-
[disableRipple]="true"
31-
[indeterminate]="item.indeterminate"
32-
[disableTransitions]="true"
33-
(change)="onCheckboxChange($event)">
34-
{{ column.formatter && !item.isSpecial ? column.formatter(item.label) : column.dataType === 'number' ? (item.label | igxdecimal:
35-
column.grid.locale) : column.dataType === 'date' ? (item.label | igxdate: column.grid.locale) : item.label }}
36-
</igx-checkbox>
37-
</igx-list-item>
38-
</div>
39-
</igx-list>
22+
<igx-list [displayDensity]="displayDensity" [style.height.px]="250" [isLoading]="isLoading">
23+
<div [style.overflow]="'hidden'" [style.position]="'relative'">
24+
<igx-list-item
25+
*igxFor="let item of data | excelStyleSearchFilter: searchValue; scrollOrientation : 'vertical'; containerSize: '250px'; itemSize: itemSize">
26+
<igx-checkbox
27+
[value]="item"
28+
tabindex="-1"
29+
[checked]="item.isSelected"
30+
[disableRipple]="true"
31+
[indeterminate]="item.indeterminate"
32+
[disableTransitions]="true"
33+
(change)="onCheckboxChange($event)">
34+
{{ column.formatter && !item.isSpecial ? column.formatter(item.label) : column.dataType === 'number' ? (item.label | igxdecimal:
35+
column.grid.locale) : column.dataType === 'date' ? (item.label | igxdate: column.grid.locale) : item.label }}
36+
</igx-checkbox>
37+
</igx-list-item>
38+
</div>
39+
40+
<ng-template igxDataLoading>
41+
<div style="display: flex; align-items: center;" class="esf-loading-indicator">
42+
<ng-container *ngTemplateOutlet="grid.esfLoadingIndicatorTemplate ? grid.esfLoadingIndicatorTemplate : defaultEsfLoadingIndicatorTemplate">
43+
</ng-container>
44+
</div>
45+
</ng-template>
46+
</igx-list>
47+
48+
<ng-template #defaultEsfLoadingIndicatorTemplate>
49+
<igx-circular-bar [indeterminate]="true">
50+
</igx-circular-bar>
51+
</ng-template>

projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
Component,
44
ChangeDetectionStrategy,
55
Input,
6-
ViewChild
6+
ViewChild,
7+
ChangeDetectorRef
78
} from '@angular/core';
89
import { IgxColumnComponent } from '../../column.component';
910
import { IgxFilterOptions } from '../../../directives/filter/filter.directive';
@@ -24,8 +25,22 @@ import { FilterListItem } from './grid.excel-style-filtering.component';
2425
})
2526
export class IgxExcelStyleSearchComponent implements AfterViewInit {
2627

28+
private _isLoading;
29+
30+
public get isLoading() {
31+
return this._isLoading;
32+
}
33+
34+
public set isLoading(value: boolean) {
35+
this._isLoading = value;
36+
this._cdr.detectChanges();
37+
}
38+
2739
public searchValue: any;
2840

41+
@Input()
42+
public grid: any;
43+
2944
@Input()
3045
public data: FilterListItem[];
3146

@@ -41,7 +56,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit {
4156
@ViewChild(IgxForOfDirective, { static: true })
4257
protected virtDir: IgxForOfDirective<any>;
4358

44-
constructor() { }
59+
constructor(private _cdr: ChangeDetectorRef) { }
4560

4661
public ngAfterViewInit() {
4762
requestAnimationFrame(() => {

projects/igniteui-angular/src/lib/grids/filtering/excel-style/grid.excel-style-filtering.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ <h4>{{ column.header || column.field }}</h4>
122122
#excelStyleSearch
123123
[column]="column"
124124
[data]="listData"
125+
[grid]="grid"
125126
[displayDensity]="grid.displayDensity">
126127
</igx-excel-style-search>
127128

projects/igniteui-angular/src/lib/grids/filtering/excel-style/grid.excel-style-filtering.component.ts

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,29 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy, AfterView
332332
}
333333

334334
public populateColumnData() {
335+
if (this.grid.loadColumnValuesOnDemand) {
336+
this.loadValuesOnDemand();
337+
} else {
338+
this.loadValuesFromGridData();
339+
}
340+
}
341+
342+
private loadValuesOnDemand() {
343+
this.excelStyleSearch.isLoading = true;
344+
this.grid.loadColumnValuesOnDemand(this.column.field, (columnUniqueValues: any[]) => {
345+
if (this.column.dataType === DataType.Date) {
346+
this.uniqueValues = Array.from(new Set(columnUniqueValues.map(val => val ? val.toDateString() : val)));
347+
this.generateFilterValues(true);
348+
} else {
349+
this.uniqueValues = Array.from(new Set(columnUniqueValues));
350+
this.generateFilterValues();
351+
}
352+
this.generateListData();
353+
this.excelStyleSearch.isLoading = false;
354+
});
355+
}
356+
357+
public loadValuesFromGridData() {
335358
let data = this.column.gridAPI.get_all_data(this.grid.id);
336359
const gridExpressionsTree: IFilteringExpressionsTree = this.grid.filteringExpressionsTree;
337360
const expressionsTree = new FilteringExpressionsTree(gridExpressionsTree.operator, gridExpressionsTree.fieldName);
@@ -354,6 +377,16 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy, AfterView
354377
if (this.column.dataType === DataType.Date) {
355378
this.uniqueValues = Array.from(new Set(data.map(record =>
356379
record[this.column.field] ? record[this.column.field].toDateString() : record[this.column.field])));
380+
this.generateFilterValues(true);
381+
} else {
382+
this.uniqueValues = Array.from(new Set(data.map(record => record[this.column.field])));
383+
this.generateFilterValues();
384+
}
385+
this.generateListData();
386+
}
387+
388+
private generateFilterValues(isDateColumn: boolean = false) {
389+
if (isDateColumn) {
357390
this.filterValues = new Set<any>(this.expressionsList.reduce((arr, e) => {
358391
if (e.expression.condition.name === 'in') {
359392
return [ ...arr, ...Array.from((e.expression.searchVal as Set<any>).values()).map(v =>
@@ -362,14 +395,16 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy, AfterView
362395
return [ ...arr, ...[e.expression.searchVal ? e.expression.searchVal.toDateString() : e.expression.searchVal] ];
363396
}, []));
364397
} else {
365-
this.uniqueValues = Array.from(new Set(data.map(record => record[this.column.field])));
366398
this.filterValues = new Set<any>(this.expressionsList.reduce((arr, e) => {
367399
if (e.expression.condition.name === 'in') {
368400
return [ ...arr, ...Array.from((e.expression.searchVal as Set<any>).values()) ];
369401
}
370402
return [ ...arr, ...[e.expression.searchVal] ];
371403
}, []));
372404
}
405+
}
406+
407+
private generateListData() {
373408
this.listData = new Array<FilterListItem>();
374409

375410
const shouldUpdateSelection = this.areExpressionsSelectable() && this.areExpressionsValuesInTheList();
@@ -395,6 +430,72 @@ export class IgxGridExcelStyleFilteringComponent implements OnDestroy, AfterView
395430
this.cdr.detectChanges();
396431
}
397432

433+
434+
435+
// public populateColumnData() {
436+
// let data = this.column.gridAPI.get_all_data(this.grid.id);
437+
// const gridExpressionsTree: IFilteringExpressionsTree = this.grid.filteringExpressionsTree;
438+
// const expressionsTree = new FilteringExpressionsTree(gridExpressionsTree.operator, gridExpressionsTree.fieldName);
439+
440+
// for (const operand of gridExpressionsTree.filteringOperands) {
441+
// if (operand instanceof FilteringExpressionsTree) {
442+
// const columnExprTree = operand as FilteringExpressionsTree;
443+
// if (columnExprTree.fieldName === this.column.field) {
444+
// break;
445+
// }
446+
// }
447+
// expressionsTree.filteringOperands.push(operand);
448+
// }
449+
450+
// if (expressionsTree.filteringOperands.length) {
451+
// const state = { expressionsTree: expressionsTree };
452+
// data = DataUtil.filter(cloneArray(data), state);
453+
// }
454+
455+
// if (this.column.dataType === DataType.Date) {
456+
// this.uniqueValues = Array.from(new Set(data.map(record =>
457+
// record[this.column.field] ? record[this.column.field].toDateString() : record[this.column.field])));
458+
// this.filterValues = new Set<any>(this.expressionsList.reduce((arr, e) => {
459+
// if (e.expression.condition.name === 'in') {
460+
// return [ ...arr, ...Array.from((e.expression.searchVal as Set<any>).values()).map(v =>
461+
// new Date(v).toDateString()) ];
462+
// }
463+
// return [ ...arr, ...[e.expression.searchVal ? e.expression.searchVal.toDateString() : e.expression.searchVal] ];
464+
// }, []));
465+
// } else {
466+
// this.uniqueValues = Array.from(new Set(data.map(record => record[this.column.field])));
467+
// this.filterValues = new Set<any>(this.expressionsList.reduce((arr, e) => {
468+
// if (e.expression.condition.name === 'in') {
469+
// return [ ...arr, ...Array.from((e.expression.searchVal as Set<any>).values()) ];
470+
// }
471+
// return [ ...arr, ...[e.expression.searchVal] ];
472+
// }, []));
473+
// }
474+
// this.listData = new Array<FilterListItem>();
475+
476+
// const shouldUpdateSelection = this.areExpressionsSelectable() && this.areExpressionsValuesInTheList();
477+
478+
// if (this.column.dataType === DataType.Boolean) {
479+
// this.addBooleanItems();
480+
// } else {
481+
// this.addItems(shouldUpdateSelection);
482+
// }
483+
484+
// this.listData.sort((a, b) => this.sortData(a, b));
485+
486+
// if (this.column.dataType === DataType.Date) {
487+
// this.uniqueValues = this.uniqueValues.map(value => new Date(value));
488+
// }
489+
490+
// if (this.containsNullOrEmpty) {
491+
// this.addBlanksItem(shouldUpdateSelection);
492+
// }
493+
494+
// this.addSelectAllItem();
495+
496+
// this.cdr.detectChanges();
497+
// }
498+
398499
private addBooleanItems() {
399500
this.selectAllSelected = true;
400501
this.selectAllIndeterminate = false;

projects/igniteui-angular/src/lib/grids/filtering/excel-style/grid.excel-style-filtering.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { IgxFilterModule } from '../../../directives/filter/filter.directive';
2929
import { IgxToggleModule } from '../../../directives/toggle/toggle.directive';
3030
import { IgxListModule } from '../../../list/list.component';
3131
import { IgxExcelStyleSearchFilterPipe } from './excel-style-search.pipe';
32+
import { IgxProgressBarModule } from '../../../progressbar/progressbar.component';
3233

3334
/**
3435
* @hidden
@@ -71,7 +72,8 @@ import { IgxExcelStyleSearchFilterPipe } from './excel-style-search.pipe';
7172
IgxCheckboxModule,
7273
IgxFilterModule,
7374
IgxToggleModule,
74-
IgxListModule
75+
IgxListModule,
76+
IgxProgressBarModule
7577
],
7678
entryComponents: [
7779
IgxGridExcelStyleFilteringComponent

projects/igniteui-angular/src/lib/grids/grid-base.component.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
250250
return this._scrollWidth;
251251
}
252252

253+
private _esfLoadingIndicatorTemplate: TemplateRef<any>;
253254
private _resourceStrings = CurrentResourceStrings.GridResStrings;
254255
private _emptyGridMessage = null;
255256
private _emptyFilteredGridMessage = null;
@@ -1000,6 +1001,19 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
10001001
}
10011002
}
10021003

1004+
@Input()
1005+
public get esfLoadingIndicatorTemplate(): TemplateRef<any> {
1006+
return this._esfLoadingIndicatorTemplate;
1007+
}
1008+
1009+
public set esfLoadingIndicatorTemplate(value: TemplateRef<any>) {
1010+
this._esfLoadingIndicatorTemplate = value;
1011+
this.cdr.markForCheck();
1012+
}
1013+
1014+
@Input()
1015+
public loadColumnValuesOnDemand: (field: string, done: (values: any[]) => void) => void;
1016+
10031017
/**
10041018
* Emitted when `IgxGridCellComponent` is clicked. Returns the `IgxGridCellComponent`.
10051019
* ```html

src/app/app.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ export class AppComponent implements OnInit {
173173
icon: 'view_column',
174174
name: 'Grid Filter Template'
175175
},
176+
{
177+
link: '/gridEsfLoadOnDemand',
178+
icon: 'view_column',
179+
name: 'Grid ESF Load On Demand'
180+
},
176181
{
177182
link: '/gridColumnMoving',
178183
icon: 'view_column',

src/app/app.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ import { GridFilterTemplateSampleComponent } from './grid-filter-template/grid-f
106106
import { GridMRLConfigSampleComponent } from './grid-multi-row-layout-config/grid-mrl-config.sample';
107107
import { GridMRLCustomNavigationSampleComponent } from './grid-mrl-custom-navigation/grid-mrl-custom-navigation';
108108
import { GridClipboardSampleComponent } from './grid-clipboard/grid-clipboard.sample';
109+
import { GridEsfLoadOnDemandComponent } from './grid-esf-load-on-demand/grid-esf-load-on-demand.component';
109110

110111

111112

@@ -204,7 +205,8 @@ const components = [
204205
GridSearchBoxComponent,
205206
GridSearchComponent,
206207
GridFilterTemplateSampleComponent,
207-
GridClipboardSampleComponent
208+
GridClipboardSampleComponent,
209+
GridEsfLoadOnDemandComponent
208210
];
209211

210212
@NgModule({
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<div class="wrapper">
2+
<app-page-header title="Grid Excel Style Filtering - Load on demand">
3+
Allows loading unique column values into the Excel Style Filtering on demand.
4+
</app-page-header>
5+
6+
<div class="sample-content">
7+
<div class="sample-column">
8+
<div class="density-chooser">
9+
<igx-buttongroup [values]="displayDensities" (onSelect)="selectDensity($event)"></igx-buttongroup>
10+
</div>
11+
<igx-grid #grid1 [data]="data" [displayDensity]="density" [showToolbar]="true"
12+
[columnHiding]="true" [allowFiltering]="true" [rowSelectable]="true"
13+
[filterMode]="'excelStyleFilter'" [width]="'900px'"
14+
[height]="'800px'" [style.zIndex]="'1'"
15+
16+
[loadColumnValuesOnDemand]="loadColumnValues"
17+
[esfLoadingIndicatorTemplate]="loadTemplate"
18+
>
19+
20+
<igx-column [field]="'ID'" [filterable]="true" [sortable]="true" [movable]="true" [dataType]="'string'"></igx-column>
21+
<igx-column [field]="'CompanyName'" [filterable]="true" [sortable]="true" [movable]="true" [dataType]="'string'"></igx-column>
22+
<igx-column [field]="'Employees'" [filterable]="true" [sortable]="true" [movable]="true" [dataType]="'number'"></igx-column>
23+
<igx-column [field]="'Contract'" [filterable]="true" [sortable]="true" [movable]="true" [dataType]="'boolean'"></igx-column>
24+
<igx-column [field]="'DateCreated'" [filterable]="true" [sortable]="true" [movable]="true" [dataType]="'date'"></igx-column>
25+
</igx-grid>
26+
</div>
27+
</div>
28+
</div>
29+
30+
<ng-template #loadTemplate>
31+
Loading ...
32+
</ng-template>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.density-chooser {
2+
margin-bottom: 16px;
3+
max-width: 900px;
4+
}

0 commit comments

Comments
 (0)