Skip to content

Commit

Permalink
fix(backend): OData/GraphQL pagination should display warning on empty (
Browse files Browse the repository at this point in the history
#632)

- add a new paginationOptions getter/setter to avoid incomplete gridOptions passed by the OData result callback, merging the gridOptions was incomplete because it was only merging with the local gridOptions instead of the local+global gridOptions
- basically we won't be able to see the Empty Dataset Warning with OData unless we modified the code and use the new setter. Keeping the old code will still work but just won't display the warning when dataset is empty
  • Loading branch information
ghiscoding committed Nov 16, 2020
1 parent 8f72e38 commit 7d32bac
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 18 deletions.
16 changes: 10 additions & 6 deletions src/app/examples/grid-odata.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ <h2>{{title}}</h2>
<span data-test="radioVersion">
<label class="radio-inline control-label" for="radio2">
<input type="radio" name="inlineRadioOptions" data-test="version2" id="radio2" checked [value]="2"
(change)="setOdataVersion(2)"> 2
(change)="setOdataVersion(2)"> 2
</label>
<label class="radio-inline control-label" for="radio4">
<input type="radio" name="inlineRadioOptions" data-test="version4" id="radio4" [value]="4"
(change)="setOdataVersion(4)"> 4
(change)="setOdataVersion(4)"> 4
</label>
</span>
<label class="checkbox-inline control-label" for="enableCount" style="margin-left: 20px">
<input type="checkbox" id="enableCount" data-test="enable-count" [checked]="isCountEnabled"
(click)="changeCountEnableFlag()">
(click)="changeCountEnableFlag()">
<span style="font-weight: bold">Enable Count</span> (add to OData query)
</label>
</div>
Expand All @@ -55,8 +55,12 @@ <h2>{{title}}</h2>
</button>
</div>

<angular-slickgrid gridId="grid5" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="dataset" (onGridStateChanged)="gridStateChanged($event)"
(onAngularGridCreated)="angularGridReady($event)">
<angular-slickgrid gridId="grid5"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[paginationOptions]="paginationOptions"
[dataset]="dataset"
(onGridStateChanged)="gridStateChanged($event)"
(onAngularGridCreated)="angularGridReady($event)">
</angular-slickgrid>
</div>
5 changes: 3 additions & 2 deletions src/app/examples/grid-odata.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
OdataOption,
OdataServiceApi,
OperatorType,
Pagination,
} from './../modules/angular-slickgrid';

const defaultPageSize = 20;
Expand Down Expand Up @@ -43,6 +44,7 @@ export class GridOdataComponent implements OnInit {
gridOptions: GridOption;
dataset = [];
metrics: Metrics;
paginationOptions: Pagination;

isCountEnabled = true;
odataVersion = 2;
Expand Down Expand Up @@ -139,11 +141,10 @@ export class GridOdataComponent implements OnInit {
if (this.isCountEnabled) {
countPropName = (this.odataVersion === 4) ? '@odata.count' : 'odata.count';
}
this.gridOptions.pagination.totalItems = data[countPropName];
this.paginationOptions = { ...this.gridOptions.pagination, totalItems: data[countPropName] };
if (this.metrics) {
this.metrics.totalItemCount = data[countPropName];
}
this.gridOptions = Object.assign({}, this.gridOptions);

// once pagination totalItems is filled, we can update the dataset
this.dataset = data['items'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const paginationServiceStub = {
totalItems: 0,
init: jest.fn(),
dispose: jest.fn(),
updateTotalItems: jest.fn(),
onPaginationVisibilityChanged: new Subject<boolean>(),
onPaginationChanged: new Subject<ServicePagination>(),
} as unknown as PaginationService;
Expand Down Expand Up @@ -1249,6 +1250,29 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
component.destroy();
});

it('should merge paginationOptions when some already exist', () => {
const mockPagination = { pageSize: 2, pageSizes: [] };
const paginationSrvSpy = jest.spyOn(paginationServiceStub, 'updateTotalItems');

component.ngAfterViewInit();
component.paginationOptions = mockPagination;

expect(component.paginationOptions).toEqual({ ...mockPagination, totalItems: 0 });
expect(paginationSrvSpy).toHaveBeenCalledWith(0, true);
});

it('should set brand new paginationOptions when none previously exist', () => {
const mockPagination = { pageSize: 2, pageSizes: [], totalItems: 1 };
const paginationSrvSpy = jest.spyOn(paginationServiceStub, 'updateTotalItems');

component.ngAfterViewInit();
component.paginationOptions = undefined;
component.paginationOptions = mockPagination;

expect(component.paginationOptions).toEqual(mockPagination);
expect(paginationSrvSpy).toHaveBeenNthCalledWith(2, 1, true);
});

it('should call trigger a gridStage change event when pagination change is triggered', () => {
const mockPagination = { pageNumber: 2, pageSize: 20 } as Pagination;
const spy = jest.spyOn(gridStateServiceStub.onGridStateChanged, 'next');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
private _isDatasetInitialized = false;
private _isPaginationInitialized = false;
private _isLocalGrid = true;
private _paginationOptions: Pagination | undefined;
private slickEmptyWarning: SlickEmptyWarningComponent;
dataView: any | null;
grid: any | null;
Expand All @@ -143,7 +144,6 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
customFooterOptions: CustomFooterOption;
locales: Locale;
metrics: Metrics;
paginationOptions: Pagination;
showCustomFooter = false;
showPagination = false;
totalItems = 0;
Expand All @@ -168,6 +168,20 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
@Input() gridId: string;
@Input() gridOptions: GridOption;

@Input()
get paginationOptions(): Pagination | undefined {
return this._paginationOptions;
}
set paginationOptions(options: Pagination | undefined) {
if (options && this._paginationOptions) {
this._paginationOptions = { ...this._paginationOptions, ...options };
} else {
this._paginationOptions = options;
}
this.gridOptions.pagination = options;
this.paginationService.updateTotalItems(options && options.totalItems || 0, true);
}

@Input()
set gridHeight(height: number) {
this._fixedHeight = height;
Expand Down Expand Up @@ -435,7 +449,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
this.showPagination = (this.gridOptions && (this.gridOptions.enablePagination || (this.gridOptions.backendServiceApi && this.gridOptions.enablePagination === undefined))) ? true : false;

if (this.gridOptions && this.gridOptions.backendServiceApi && this.gridOptions.pagination) {
const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this.paginationOptions);
const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
// when we have a totalCount use it, else we'll take it from the pagination object
// only update the total items if it's different to avoid refreshing the UI
const totalRecords = totalCount !== undefined ? totalCount : (this.gridOptions && this.gridOptions.pagination && this.gridOptions.pagination.totalItems);
Expand Down Expand Up @@ -783,7 +797,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
// make sure the dataset is initialized (if not it will throw an error that it cannot getLength of null)
this._dataset = this._dataset || [];
this.gridOptions = this.mergeGridOptions(this.gridOptions);
this.paginationOptions = this.gridOptions.pagination;
this._paginationOptions = this.gridOptions.pagination;
this.locales = this.gridOptions && this.gridOptions.locales || Constants.locales;
this.backendServiceApi = this.gridOptions && this.gridOptions.backendServiceApi;
this.createBackendApiInternalPostProcessCallback(this.gridOptions);
Expand Down Expand Up @@ -1007,14 +1021,14 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
private loadLocalGridPagination() {
if (this.gridOptions) {
this.totalItems = Array.isArray(this.dataset) ? this.dataset.length : 0;
if (this.paginationOptions && this.dataView && this.dataView.getPagingInfo) {
if (this._paginationOptions && this.dataView && this.dataView.getPagingInfo) {
const slickPagingInfo = this.dataView.getPagingInfo() || {};
if (slickPagingInfo.hasOwnProperty('totalRows') && this.paginationOptions.totalItems !== slickPagingInfo.totalRows) {
if (slickPagingInfo.hasOwnProperty('totalRows') && this._paginationOptions.totalItems !== slickPagingInfo.totalRows) {
this.totalItems = slickPagingInfo.totalRows;
}
}
this.paginationOptions.totalItems = this.totalItems;
const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this.paginationOptions);
this._paginationOptions.totalItems = this.totalItems;
const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
this.initializePaginationService(paginationOptions);
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/app/modules/angular-slickgrid/services/pagination.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ export class PaginationService {
if (this._isLocalGrid && this.dataView) {
this._eventHandler.subscribe(this.dataView.onPagingInfoChanged, (e, pagingInfo) => {
if (this._totalItems !== pagingInfo.totalRows) {
this._totalItems = pagingInfo.totalRows;
this._paginationOptions.totalItems = this._totalItems;
this.refreshPagination(false, false);
this.updateTotalItems(pagingInfo.totalRows);
}
});
dataView.setRefreshHints({ isFilterUnchanged: true });
Expand Down Expand Up @@ -367,6 +365,14 @@ export class PaginationService {
// private functions
// --------------------

updateTotalItems(totalItems: number, triggerChangedEvent = false) {
this._totalItems = totalItems;
if (this._paginationOptions) {
this._paginationOptions.totalItems = totalItems;
this.refreshPagination(false, triggerChangedEvent);
}
}

/**
* When item is added or removed, we will refresh the numbers on the pagination however we won't trigger a backend change
* This will have a side effect though, which is that the "To" count won't be matching the "items per page" count,
Expand Down
7 changes: 7 additions & 0 deletions test/cypress/integration/example05.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ describe('Example 5 - OData Grid', () => {

// wait for the query to finish
cy.get('[data-test=status]').should('contain', 'done');

cy.get('.slick-empty-data-warning:visible')
.contains('No data to display.');
});

it('should display page 0 of 0 but hide pagination from/to numbers when filtered data "xy" returns an empty dataset', () => {
Expand Down Expand Up @@ -554,6 +557,10 @@ describe('Example 5 - OData Grid', () => {
// wait for the query to finish
cy.get('[data-test=status]').should('contain', 'done');

cy.get('.slick-empty-data-warning')
.contains('No data to display.')
.should('not.be.visible');

cy.window().then((win) => {
expect(win.console.log).to.have.callCount(2);
expect(win.console.log).to.be.calledWith('Client sample, Grid State changed:: ', { newValues: [{ columnId: 'name', searchTerms: ['x'] }], type: 'filter' });
Expand Down

0 comments on commit 7d32bac

Please sign in to comment.