Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.

Commit a3a47de

Browse files
authored
Merge pull request #383 from ghiscoding/fix-pagination-grid-state
fix(state): Clear Sort should trigger only 1 event & fix Pagination
2 parents 411b0be + 8e4f931 commit a3a47de

File tree

11 files changed

+108
-35
lines changed

11 files changed

+108
-35
lines changed

src/app/modules/angular-slickgrid/components/__tests__/angular-slickgrid-constructor.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,12 +1124,13 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
11241124
});
11251125

11261126
it('should call trigger a gridStage change event when "onPaginationChanged" from the Pagination Service is triggered', () => {
1127-
const mockPagination = { pageNumber: 2, pageSize: 20, pageSizes: [5, 10, 15, 20] } as Pagination;
1127+
const mockPagination = { pageNumber: 2, pageSize: 20 } as Pagination;
11281128
const mockServicePagination = {
11291129
...mockPagination,
11301130
dataFrom: 5,
11311131
dataTo: 10,
11321132
pageCount: 1,
1133+
pageSizes: [5, 10, 15, 20],
11331134
} as ServicePagination;
11341135
const spy = jest.spyOn(gridStateServiceStub.onGridStateChanged, 'next');
11351136
jest.spyOn(gridStateServiceStub, 'getCurrentGridState').mockReturnValue({ columns: [], pagination: mockPagination } as GridState);

src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,14 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
309309
if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
310310
this.gridService.setSelectedRows([]);
311311
}
312-
const { pageNumber, pageSize, pageSizes } = pagination;
312+
const { pageNumber, pageSize } = pagination;
313313
if (this.sharedService) {
314314
if (pageSize) {
315-
this.sharedService.currentPagination = { pageNumber, pageSize, pageSizes };
315+
this.sharedService.currentPagination = { pageNumber, pageSize };
316316
}
317317
}
318318
this.gridStateService.onGridStateChanged.next({
319-
change: { newValues: { pageNumber, pageSize, pageSizes }, type: GridStateType.pagination },
319+
change: { newValues: { pageNumber, pageSize }, type: GridStateType.pagination },
320320
gridState: this.gridStateService.getCurrentGridState()
321321
});
322322
}

src/app/modules/angular-slickgrid/models/currentPagination.interface.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,4 @@ export interface CurrentPagination {
44

55
/** Grid page size */
66
pageSize: number;
7-
8-
/** The available page sizes */
9-
pageSizes: number[];
107
}

src/app/modules/angular-slickgrid/services/__tests__/pagination.service.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ describe('PaginationService', () => {
164164
service.changeItemPerPage(30);
165165

166166
expect(service.getCurrentPageNumber()).toBe(0);
167-
expect(service.getCurrentItemPerPageCount()).toBe(30);
167+
expect(service.getCurrentItemPerPage()).toBe(30);
168168
});
169169

170170
it('should be on page 1 with 2 pages when total items is 51 and we set 50 per page', () => {
@@ -176,7 +176,7 @@ describe('PaginationService', () => {
176176
service.changeItemPerPage(50);
177177

178178
expect(service.getCurrentPageNumber()).toBe(1);
179-
expect(service.getCurrentItemPerPageCount()).toBe(50);
179+
expect(service.getCurrentItemPerPage()).toBe(50);
180180
});
181181

182182
it('should be on page 1 with 2 pages when total items is 100 and we set 50 per page', () => {
@@ -188,7 +188,7 @@ describe('PaginationService', () => {
188188
service.changeItemPerPage(50);
189189

190190
expect(service.getCurrentPageNumber()).toBe(1);
191-
expect(service.getCurrentItemPerPageCount()).toBe(50);
191+
expect(service.getCurrentItemPerPage()).toBe(50);
192192
});
193193
});
194194

src/app/modules/angular-slickgrid/services/backend-utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ main.onBackendError = function backendError(e: any, backendApi: BackendServiceAp
4848
main.executeBackendCallback = function exeBackendCallback(backendServiceApi: BackendServiceApi, query: string, args: any, startTime: Date, totalItems: number, emitActionChangedCallback?: (type: EmitterType) => void, httpCancelRequests$?: Subject<void>) {
4949
if (backendServiceApi) {
5050
// emit an onFilterChanged event when it's not called by a clear filter
51-
if (args && !args.clearFilterTriggered) {
51+
if (args && !args.clearFilterTriggered && !args.clearSortTriggered) {
5252
emitActionChangedCallback(EmitterType.remote);
5353
}
5454

src/app/modules/angular-slickgrid/services/graphql.service.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ export class GraphqlService implements BackendService {
259259
this._currentPagination = {
260260
pageNumber: 1,
261261
pageSize: paginationOptions.first || DEFAULT_PAGE_SIZE,
262-
pageSizes: this._gridOptions && this._gridOptions.pagination && this._gridOptions.pagination.pageSizes,
263262
};
264263

265264
this.updateOptions({ paginationOptions });
@@ -456,11 +455,10 @@ export class GraphqlService implements BackendService {
456455
* @param newPage
457456
* @param pageSize
458457
*/
459-
updatePagination(newPage: number, pageSize: number, pageSizes?: number[]) {
458+
updatePagination(newPage: number, pageSize: number) {
460459
this._currentPagination = {
461460
pageNumber: newPage,
462461
pageSize,
463-
pageSizes,
464462
};
465463

466464
let paginationOptions;

src/app/modules/angular-slickgrid/services/grid-odata.service.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ export class GridOdataService implements BackendService {
7979
this._currentPagination = {
8080
pageNumber: 1,
8181
pageSize: this._odataService.options.top || this.defaultOptions.top || DEFAULT_PAGE_SIZE,
82-
pageSizes: this._gridOptions && this._gridOptions.pagination && this._gridOptions.pagination.pageSizes,
8382
};
8483
}
8584

@@ -399,11 +398,10 @@ export class GridOdataService implements BackendService {
399398
* @param newPage
400399
* @param pageSize
401400
*/
402-
updatePagination(newPage: number, pageSize: number, pageSizes?: number[]) {
401+
updatePagination(newPage: number, pageSize: number) {
403402
this._currentPagination = {
404403
pageNumber: newPage,
405404
pageSize,
406-
pageSizes,
407405
};
408406

409407
// unless user specifically set "enablePagination" to False, we'll update pagination options in every other cases

src/app/modules/angular-slickgrid/services/pagination.service.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Injectable } from '@angular/core';
22
import { Subscription, isObservable, Subject } from 'rxjs';
3+
import * as isequal_ from 'lodash.isequal';
4+
const isequal = isequal_; // patch to fix rollup to work
35

46
import { BackendServiceApi, CurrentPagination, GraphqlResult, GraphqlPaginatedResult, Pagination, ServicePagination } from '../models';
57
import { FilterService } from './filter.service';
@@ -69,7 +71,7 @@ export class PaginationService {
6971
set totalItems(totalItems: number) {
7072
this._totalItems = totalItems;
7173
if (this._initialized) {
72-
this.refreshPagination(false, false);
74+
this.refreshPagination();
7375
}
7476
}
7577

@@ -131,7 +133,7 @@ export class PaginationService {
131133
return this._pageNumber;
132134
}
133135

134-
getCurrentPagination(): CurrentPagination {
136+
getCurrentPagination(): CurrentPagination & { pageSizes: number[] } {
135137
return {
136138
pageNumber: this._pageNumber,
137139
pageSize: this._itemsPerPage,
@@ -151,7 +153,7 @@ export class PaginationService {
151153
};
152154
}
153155

154-
getCurrentItemPerPageCount(): number {
156+
getCurrentItemPerPage(): number {
155157
return this._itemsPerPage;
156158
}
157159

@@ -211,6 +213,7 @@ export class PaginationService {
211213
refreshPagination(isPageNumberReset: boolean = false, triggerChangedEvent = true) {
212214
// trigger an event to inform subscribers
213215
this.onPaginationRefreshed.next(true);
216+
const previousPagination = { ...this.getCurrentPagination() };
214217

215218
if (this._paginationOptions) {
216219
const pagination = this._paginationOptions;
@@ -247,10 +250,12 @@ export class PaginationService {
247250
this.recalculateFromToIndexes();
248251
}
249252
this._pageCount = Math.ceil(this._totalItems / this._itemsPerPage);
250-
if (triggerChangedEvent) {
251-
this.onPaginationChanged.next(this.getFullPagination());
253+
const currentPagination = this.getCurrentPagination();
254+
this.sharedService.currentPagination = currentPagination;
255+
256+
if (triggerChangedEvent && !isequal(previousPagination, currentPagination)) {
257+
this.onPaginationChanged.next(currentPagination);
252258
}
253-
this.sharedService.currentPagination = this.getCurrentPagination();
254259
}
255260

256261
processOnPageChanged(pageNumber: number, event?: Event | undefined): Promise<any> {
@@ -307,7 +312,7 @@ export class PaginationService {
307312
this._pageNumber = 0;
308313
} else {
309314
this._dataFrom = this._pageNumber > 1 ? ((this._pageNumber * this._itemsPerPage) - this._itemsPerPage + 1) : 1;
310-
this._dataTo = (this._totalItems < this._itemsPerPage) ? this._totalItems : (this._pageNumber * this._itemsPerPage);
315+
this._dataTo = (this._totalItems < this._itemsPerPage) ? this._totalItems : ((this._pageNumber || 1) * this._itemsPerPage);
311316
if (this._dataTo > this._totalItems) {
312317
this._dataTo = this._totalItems;
313318
}

src/app/modules/angular-slickgrid/services/sort.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ export class SortService {
108108
// however for a local grid, we need to pass a sort column and so we will sort by the 1st column
109109
if (triggerQueryEvent) {
110110
if (this._isBackendGrid) {
111-
this.onBackendSortChanged(undefined, { grid: this._grid, sortCols: [] });
111+
this.onBackendSortChanged(undefined, { grid: this._grid, sortCols: [], clearSortTriggered: true });
112112
} else {
113113
if (this._columnDefinitions && Array.isArray(this._columnDefinitions)) {
114-
this.onLocalSortChanged(this._grid, this._dataView, new Array({ sortAsc: true, sortCol: this._columnDefinitions[0] }));
114+
this.onLocalSortChanged(this._grid, this._dataView, new Array({ sortAsc: true, sortCol: this._columnDefinitions[0], clearSortTriggered: true }));
115115
}
116116
}
117117
} else if (this._isBackendGrid) {
@@ -219,7 +219,7 @@ export class SortService {
219219
return sortCols;
220220
}
221221

222-
onBackendSortChanged(event: Event, args: any) {
222+
onBackendSortChanged(event: Event, args: { multiColumnSort?: boolean; grid: any; sortCols: ColumnSort[]; clearSortTriggered?: boolean }) {
223223
if (!args || !args.grid) {
224224
throw new Error('Something went wrong when trying to bind the "onBackendSortChanged(event, args)" function, it seems that "args" is not populated correctly');
225225
}

test/cypress/integration/example05.spec.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('Example 5 - OData Grid', () => {
5656

5757
cy.window().then((win) => {
5858
expect(win.console.log).to.have.callCount(1);
59-
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 3, pageSize: 20, pageSizes: [10, 15, 20, 25, 30, 40, 50, 75, 100] }, type: 'pagination' });
59+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 3, pageSize: 20 }, type: 'pagination' });
6060
});
6161
});
6262

@@ -87,6 +87,11 @@ describe('Example 5 - OData Grid', () => {
8787
.should(($span) => {
8888
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10&$orderby=Name asc&$filter=(Gender eq 'male')`);
8989
});
90+
91+
cy.window().then((win) => {
92+
expect(win.console.log).to.have.callCount(1);
93+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 1, pageSize: 10 }, type: 'pagination' });
94+
});
9095
});
9196

9297
it('should change Pagination to last page', () => {
@@ -115,6 +120,11 @@ describe('Example 5 - OData Grid', () => {
115120
.should(($span) => {
116121
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10&$skip=40&$orderby=Name asc&$filter=(Gender eq 'male')`);
117122
});
123+
124+
cy.window().then((win) => {
125+
expect(win.console.log).to.have.callCount(1);
126+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 5, pageSize: 10 }, type: 'pagination' });
127+
});
118128
});
119129

120130
it('should change Pagination to first page using the external button', () => {
@@ -144,6 +154,11 @@ describe('Example 5 - OData Grid', () => {
144154
.should(($span) => {
145155
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10&$orderby=Name asc&$filter=(Gender eq 'male')`);
146156
});
157+
158+
cy.window().then((win) => {
159+
expect(win.console.log).to.have.callCount(1);
160+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 1, pageSize: 10 }, type: 'pagination' });
161+
});
147162
});
148163

149164
it('should change Pagination to last page using the external button', () => {
@@ -173,6 +188,11 @@ describe('Example 5 - OData Grid', () => {
173188
.should(($span) => {
174189
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10&$skip=40&$orderby=Name asc&$filter=(Gender eq 'male')`);
175190
});
191+
192+
cy.window().then((win) => {
193+
expect(win.console.log).to.have.callCount(1);
194+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 5, pageSize: 10 }, type: 'pagination' });
195+
});
176196
});
177197

178198
it('should Clear all Filters and expect to go back to first page', () => {
@@ -211,6 +231,12 @@ describe('Example 5 - OData Grid', () => {
211231
.should(($span) => {
212232
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10&$orderby=Name asc`);
213233
});
234+
235+
cy.window().then((win) => {
236+
expect(win.console.log).to.have.callCount(2);
237+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: [], type: 'filter' });
238+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 1, pageSize: 10 }, type: 'pagination' });
239+
});
214240
});
215241

216242
it('should Clear all Sorting', () => {
@@ -232,6 +258,11 @@ describe('Example 5 - OData Grid', () => {
232258
.should(($span) => {
233259
expect($span.text()).to.eq(`$inlinecount=allpages&$top=10`);
234260
});
261+
262+
cy.window().then((win) => {
263+
expect(win.console.log).to.have.callCount(1);
264+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: [], type: 'sorter' });
265+
});
235266
});
236267

237268
it('should use "substringof" when OData version is set to 2', () => {
@@ -476,18 +507,18 @@ describe('Example 5 - OData Grid', () => {
476507
cy.get('.search-filter.filter-name')
477508
.find('input')
478509
.clear()
479-
.type('xyz');
510+
.type('xy');
480511

481512
cy.get('[data-test=odata-query-result]')
482513
.should(($span) => {
483-
expect($span.text()).to.eq(`$top=10&$filter=(contains(Name, 'xyz'))`);
514+
expect($span.text()).to.eq(`$top=10&$filter=(contains(Name, 'xy'))`);
484515
});
485516

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

490-
it('should display page 0 of 0 but hide pagination from/to numbers when filtered data "xyz" returns an empty dataset', () => {
521+
it('should display page 0 of 0 but hide pagination from/to numbers when filtered data "xy" returns an empty dataset', () => {
491522
cy.get('[data-test=page-number-input]')
492523
.invoke('val')
493524
.then(pageNumber => expect(pageNumber).to.eq('0'));
@@ -506,14 +537,14 @@ describe('Example 5 - OData Grid', () => {
506537

507538
cy.get('[data-test=odata-query-result]')
508539
.should(($span) => {
509-
expect($span.text()).to.eq(`$top=10&$filter=(contains(Name, 'xyz'))`);
540+
expect($span.text()).to.eq(`$top=10&$filter=(contains(Name, 'xy'))`);
510541
});
511542
});
512543

513544
it('should erase part of the filter so that it filters with "x"', () => {
514545
cy.get('.search-filter.filter-name')
515546
.find('input')
516-
.type('{backspace}{backspace}');
547+
.type('{backspace}');
517548

518549
cy.get('[data-test=odata-query-result]')
519550
.should(($span) => {
@@ -526,7 +557,7 @@ describe('Example 5 - OData Grid', () => {
526557
cy.window().then((win) => {
527558
expect(win.console.log).to.have.callCount(2);
528559
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: [{ columnId: 'name', searchTerms: ['x'] }], type: 'filter' });
529-
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 0, pageSize: 10, pageSizes: [10, 15, 20, 25, 30, 40, 50, 75, 100] }, type: 'pagination' });
560+
expect(win.console.log).to.be.calledWith("Client sample, Grid State changed:: ", { newValues: { pageNumber: 1, pageSize: 10 }, type: 'pagination' });
530561
});
531562
});
532563

0 commit comments

Comments
 (0)