Skip to content

Commit 8f716a4

Browse files
ChronosSFmpavlinov
authored andcommitted
igxGrid - changing isLoading to not depend on data state (#5777)
* feat(grid): add overlay loading logic for flat grid #5517 * chore(*): some additions to impl * chore(*): fixing most things * chore(*): finalizing changes in code * test(*): changing tests to match new behavior #5517
1 parent 452fb71 commit 8f716a4

File tree

15 files changed

+155
-19
lines changed

15 files changed

+155
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ For more information about the theming please read our [documentation](https://w
7676
- **Breaking Change** `onRowSelectionChange` event arguments are changed. The `row` property has been removed and the properties `added`, `removed` and `cancel` are newly added.
7777
- **Breaking Change** `igxExcelStylePinningTemplate` directive is renamed to `igxExcelStylePinning`.
7878
- **Breaking Change** `onRowDragEnd` and `onRowDragStart` event arguments are changed - `owner` now holds reference to the grid component instance, while `dragDirective` hold reference to the drag directive.
79+
- **Behavioral Change** The behavior of the `isLoading` input no longer depends on the state of the data the grid binds to. Setting it to `true` now shows a loading indicator until it is disabled by the user.
7980
- `IgxCombo`
8081
- Combo selection is now consistent when `valueKey` is defined. When `valueKey` is specified, selection is based on the value keys of the items. For example:
8182
```html

projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,10 @@
431431
@extend %igx-grid__outlet !optional;
432432
}
433433

434+
@include e(loading-outlet) {
435+
@extend %igx-grid__loading-outlet !optional;
436+
}
437+
434438
@include e(row-editing-outlet) {
435439
@extend %igx-grid__row-editing-outlet !optional;
436440
}

projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,15 @@
19921992
position: fixed;
19931993
}
19941994

1995+
%igx-grid__loading-outlet {
1996+
z-index: 10003;
1997+
1998+
%circular-display {
1999+
width: rem(50);
2000+
height: rem(50);
2001+
}
2002+
}
2003+
19952004
%igx-grid__row-editing-outlet {
19962005
z-index: 10000;
19972006
position: absolute;

projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ describe('igxExpansionPanel', () => {
10101010
expect(grid.attributes.getNamedItem('ng-reflect-auto-generate').nodeValue).toEqual('true');
10111011
expect(grid.attributes.getNamedItem('ng-reflect-width').nodeValue).toEqual(fixture.componentInstance.width);
10121012
expect(grid.attributes.getNamedItem('ng-reflect-height').nodeValue).toEqual(fixture.componentInstance.height);
1013-
expect(grid.childElementCount).toEqual(6);
1013+
expect(grid.childElementCount).toEqual(7);
10141014
}));
10151015
it('Should apply all appropriate classes on combo initialization_image + text content', fakeAsync(() => {
10161016
const fixture: ComponentFixture<IgxExpansionPanelImageComponent> = TestBed.createComponent(IgxExpansionPanelImageComponent);

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

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import {
4646
IgxOverlayService,
4747
OverlaySettings,
4848
PositionSettings,
49-
ConnectedPositioningStrategy
49+
ConnectedPositioningStrategy,
50+
ContainerPositionStrategy
5051
} from '../services/index';
5152
import { GridBaseAPIService } from './api.service';
5253
import { IgxGridCellComponent } from './cell.component';
@@ -845,9 +846,13 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
845846
* ```
846847
* @memberof IgxGridBaseComponent
847848
*/
849+
@WatchChanges()
848850
@Input()
849851
set isLoading(value: boolean) {
850-
this._isLoading = value;
852+
if (this._isLoading !== value) {
853+
this._isLoading = value;
854+
this.evaluateLoadingState();
855+
}
851856
this.notifyChanges();
852857
}
853858

@@ -1650,6 +1655,18 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
16501655
@ViewChild(IgxGridColumnResizerComponent, { static: false })
16511656
public resizeLine: IgxGridColumnResizerComponent;
16521657

1658+
/**
1659+
* @hidden
1660+
*/
1661+
@ViewChild('loadingOverlay', { static: true })
1662+
public loadingOverlay: ElementRef;
1663+
1664+
/**
1665+
* @hidden
1666+
*/
1667+
@ViewChild('igxLoadingOverlayOutlet', { read: IgxOverlayOutletDirective, static: true })
1668+
public loadingOutlet: IgxOverlayOutletDirective;
1669+
16531670
/**
16541671
* @hidden
16551672
*/
@@ -2728,6 +2745,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
27282745
protected _baseFontSize: number;
27292746
private _horizontalForOfs: Array<IgxGridForOfDirective<any>> = [];
27302747
private _multiRowLayoutRowSize = 1;
2748+
protected _loadingId;
27312749

27322750
// Caches
27332751
private _totalWidth = NaN;
@@ -2927,6 +2945,7 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
29272945
this.verticalScrollContainer.onDataChanging.pipe(destructor, filter(() => !this._init)).subscribe(($event) => {
29282946
this.calculateGridHeight();
29292947
$event.containerSize = this.calcHeight;
2948+
this.evaluateLoadingState();
29302949
this.notifyChanges(true);
29312950
});
29322951

@@ -5642,6 +5661,30 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
56425661
}
56435662
}
56445663

5664+
/**
5665+
* Should be called when data and/or isLoading input changes so that the overlay can be
5666+
* hidden/shown based on the current value of shouldOverlayLoading
5667+
*/
5668+
protected evaluateLoadingState() {
5669+
if (this.shouldOverlayLoading) {
5670+
// a new overlay should be shown
5671+
const overlaySettings: OverlaySettings = {
5672+
outlet: this.loadingOutlet,
5673+
closeOnOutsideClick: false,
5674+
positionStrategy: new ContainerPositionStrategy()
5675+
};
5676+
if (!this._loadingId) {
5677+
this._loadingId = this.overlayService.attach(this.loadingOverlay, overlaySettings);
5678+
this.overlayService.show(this._loadingId, overlaySettings);
5679+
}
5680+
} else {
5681+
if (this._loadingId) {
5682+
this.overlayService.hide(this._loadingId);
5683+
this._loadingId = null;
5684+
}
5685+
}
5686+
}
5687+
56455688
openRowOverlay(id) {
56465689
this.configureRowEditingOverlay(id, this.rowList.length <= MIN_ROW_EDITING_COUNT_THRESHOLD);
56475690

@@ -5829,6 +5872,13 @@ export abstract class IgxGridBaseComponent extends DisplayDensityBase implements
58295872
return this._exportCsv;
58305873
}
58315874

5875+
/**
5876+
* @hidden
5877+
*/
5878+
get shouldOverlayLoading(): boolean {
5879+
return this.isLoading && this.data && this.data.length > 0;
5880+
}
5881+
58325882
/**
58335883
* @hidden
58345884
*/

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@
138138
<ng-container *ngTemplateOutlet="template"></ng-container>
139139
<div class="igx-grid__row-editing-outlet" igxOverlayOutlet #igxRowEditingOverlayOutlet></div>
140140
</div>
141+
<div [style.display]="shouldOverlayLoading ? 'flex' : 'none'" #loadingOverlay>
142+
<igx-circular-bar [indeterminate]="true">
143+
</igx-circular-bar>
144+
</div>
141145
<span *ngIf="hasMovableColumns && draggedColumn" [igxColumnMovingDrop]="parentVirtDir" [attr.droppable]="true"
142146
id="right" class="igx-grid__scroll-on-drag-right"></span>
143147
<div [hidden]='!hasVerticalSroll()' class="igx-grid__tbody-scrollbar" [style.width.px]="scrollWidth"
@@ -266,4 +270,5 @@
266270
</ng-template>
267271

268272
<igx-grid-column-resizer *ngIf="colResizingService.showResizer"></igx-grid-column-resizer>
273+
<div class="igx-grid__loading-outlet" #igxLoadingOverlayOutlet igxOverlayOutlet></div>
269274
<div class="igx-grid__outlet" #igxFilteringOverlayOutlet igxOverlayOutlet></div>

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ describe('IgxGrid Component Tests #grid', () => {
358358
tick(16);
359359

360360
const grid = fixture.componentInstance.grid;
361+
const gridElement = fixture.debugElement.query(By.css('.igx-grid'));
361362
const gridBody = fixture.debugElement.query(By.css(TBODY_CLASS));
362363
let loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
363364

@@ -373,6 +374,10 @@ describe('IgxGrid Component Tests #grid', () => {
373374
loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
374375
expect(loadingIndicator).toBeNull();
375376

377+
// the overlay should be shown
378+
loadingIndicator = gridElement.query(By.css('.igx-grid__loading-outlet'));
379+
expect(loadingIndicator.nativeElement.children.length).not.toBe(0);
380+
376381
// Check for empty filter grid message and body less than 100px
377382
const columns = fixture.componentInstance.grid.columns;
378383
grid.filter(columns[0].field, 546000, IgxNumberFilteringOperand.instance().condition('equals'));
@@ -393,6 +398,10 @@ describe('IgxGrid Component Tests #grid', () => {
393398

394399
loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
395400
expect(loadingIndicator).not.toBeNull();
401+
402+
// the overlay should be hidden
403+
loadingIndicator = gridElement.query(By.css('.igx-grid__loading-outlet'));
404+
expect(loadingIndicator.nativeElement.children.length).toBe(0);
396405
}));
397406

398407
it('should render loading indicator when loading is enabled and autoGenerate is enabled', fakeAsync(() => {
@@ -478,6 +487,50 @@ describe('IgxGrid Component Tests #grid', () => {
478487
expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBeGreaterThan(500);
479488
}));
480489

490+
it('should remove loading overlay when isLoading is set to false', fakeAsync(() => {
491+
const fixture = TestBed.createComponent(IgxGridTestComponent);
492+
fixture.componentInstance.data = [];
493+
fixture.componentInstance.grid.isLoading = true;
494+
fixture.detectChanges();
495+
tick(16);
496+
497+
const grid = fixture.componentInstance.grid;
498+
const gridElement = fixture.debugElement.query(By.css('.igx-grid'));
499+
const gridBody = fixture.debugElement.query(By.css(TBODY_CLASS));
500+
let loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
501+
502+
expect(loadingIndicator).not.toBeNull();
503+
expect(gridBody.nativeElement.textContent).not.toEqual(grid.emptyFilteredGridMessage);
504+
505+
// Check for loaded rows in grid's container
506+
fixture.componentInstance.generateData(30);
507+
fixture.detectChanges();
508+
tick(1000);
509+
expect(parseInt(window.getComputedStyle(gridBody.nativeElement).height, 10)).toBe(548);
510+
511+
loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
512+
expect(loadingIndicator).toBeNull();
513+
514+
// the overlay should be shown
515+
loadingIndicator = gridElement.query(By.css('.igx-grid__loading-outlet'));
516+
expect(loadingIndicator.nativeElement.children.length).not.toBe(0);
517+
518+
grid.isLoading = false;
519+
tick(16);
520+
expect(loadingIndicator.nativeElement.children.length).toBe(0);
521+
522+
// Clearing grid's data and check for empty grid message
523+
fixture.componentInstance.clearData();
524+
fixture.detectChanges();
525+
tick(100);
526+
527+
// isLoading is still false so the empty data message should show, not the loading indicator
528+
loadingIndicator = gridBody.query(By.css('.igx-grid__loading'));
529+
expect(loadingIndicator).toBeNull();
530+
531+
expect(gridBody.nativeElement.textContent).toEqual(grid.emptyGridMessage);
532+
}));
533+
481534
it('should render empty message when grid height is 100%', fakeAsync(() => {
482535
const fixture = TestBed.createComponent(IgxGridEmptyMessage100PercentComponent);
483536
fixture.detectChanges();

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
<igx-grid-filtering-row #filteringRow [style.width.px]='calcWidth' *ngIf="filteringService.isFilterRowVisible"
6262
[column]="filteringService.filteredColumn"></igx-grid-filtering-row>
6363
</div>
64+
<div [style.display]="shouldOverlayLoading ? 'flex' : 'none'" #loadingOverlay>
65+
<igx-circular-bar [indeterminate]="true">
66+
</igx-circular-bar>
67+
</div>
6468
<span *ngIf="hasMovableColumns && draggedColumn" [igxColumnMovingDrop]="parentVirtDir" [attr.droppable]="true"
6569
id="right" class="igx-grid__scroll-on-drag-right"></span>
6670
<div class="igx-grid__thead-thumb" [hidden]='!hasVerticalSroll()' [style.width.px]="scrollWidth"></div>
@@ -231,4 +235,5 @@
231235
</ng-template>
232236

233237
<igx-grid-column-resizer *ngIf="colResizingService.showResizer"></igx-grid-column-resizer>
238+
<div class="igx-grid__loading-outlet" #igxLoadingOverlayOutlet igxOverlayOutlet></div>
234239
<div class="igx-grid__outlet" #igxFilteringOverlayOutlet igxOverlayOutlet></div>

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ describe('IgxHierarchicalGrid Row Islands #hGrid', () => {
637637
expect(child2._destroyed).toBeTruthy();
638638
}));
639639

640-
it(' should emit child grid events with the related child grid instance as an event arg.', async() => {
640+
it('should emit child grid events with the related child grid instance as an event arg.', async() => {
641641
const row = hierarchicalGrid.getRowByIndex(0) as IgxHierarchicalRowComponent;
642642
UIInteractions.clickElement(row.expander);
643643
fixture.detectChanges();

projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
[column]="filteringService.filteredColumn"></igx-grid-filtering-row>
5151
</div>
5252
<div class="igx-grid__thead-thumb" [hidden]='!hasVerticalSroll()' [style.width.px]="scrollWidth"></div>
53+
<div [style.display]="shouldOverlayLoading ? 'flex' : 'none'" #loadingOverlay>
54+
<igx-circular-bar [indeterminate]="true">
55+
</igx-circular-bar>
56+
</div>
5357
<span *ngIf="hasMovableColumns && draggedColumn" [igxColumnMovingDrop]="parentVirtDir" [attr.droppable]="true"
5458
id="right" class="igx-grid__scroll-on-drag-right"></span>
5559
</div>
@@ -206,4 +210,5 @@
206210
</ng-template>
207211

208212
<igx-grid-column-resizer *ngIf="colResizingService.showResizer"></igx-grid-column-resizer>
213+
<div class="igx-grid__loading-outlet" #igxLoadingOverlayOutlet igxOverlayOutlet></div>
209214
<div class="igx-grid__outlet" #igxFilteringOverlayOutlet igxOverlayOutlet></div>

0 commit comments

Comments
 (0)