diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example09.html b/examples/vite-demo-vanilla-bundle/src/examples/example09.html
index 952839de5..783e87ef6 100644
--- a/examples/vite-demo-vanilla-bundle/src/examples/example09.html
+++ b/examples/vite-demo-vanilla-bundle/src/examples/example09.html
@@ -15,6 +15,7 @@
error and its only purpose is to demo what would happen when you encounter a backend server error
(the UI should rollback to previous state before you did the action).
Also changing Page Size to 50,000 will also throw which again is for demo purposes.
+ Moreover, the example will persist changes in the local storage, so if you refresh the page, it will remember your last settings.
@@ -29,6 +30,9 @@
Set Sorting Dynamically
+
+ Clear Local Storage
+
Throw Error Going to Last Page...
diff --git a/examples/vite-demo-vanilla-bundle/src/examples/example09.ts b/examples/vite-demo-vanilla-bundle/src/examples/example09.ts
index 81c4f3488..2fba869d5 100644
--- a/examples/vite-demo-vanilla-bundle/src/examples/example09.ts
+++ b/examples/vite-demo-vanilla-bundle/src/examples/example09.ts
@@ -1,11 +1,12 @@
import { BindingEventService } from '@slickgrid-universal/binding';
-import { type Column, FieldType, Filters, type GridOption, type GridStateChange, type Metrics, OperatorType, } from '@slickgrid-universal/common';
+import { type Column, FieldType, Filters, type GridOption, type GridStateChange, type Metrics, OperatorType, type GridState, } from '@slickgrid-universal/common';
import { GridOdataService, type OdataServiceApi, type OdataOption } from '@slickgrid-universal/odata';
import { Slicker, type SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { ExampleGridOptions } from './example-grid-options';
import Data from './data/customers_100.json';
import './example09.scss';
+const STORAGE_KEY = 'slickgrid-universal-example09-gridstate';
const defaultPageSize = 20;
export default class Example09 {
@@ -112,7 +113,7 @@ export default class Example09 {
pageSizes: [10, 20, 50, 100, 500, 50000],
pageSize: defaultPageSize,
},
- presets: {
+ presets: localStorage.getItem(STORAGE_KEY) ? JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}') as GridState : {
// you can also type operator as string, e.g.: operator: 'EQ'
filters: [
// { columnId: 'name', searchTerms: ['w'], operator: OperatorType.startsWith },
@@ -224,18 +225,18 @@ export default class Example09 {
if (param.includes('$filter=')) {
const filterBy = param.substring('$filter='.length).replace('%20', ' ');
if (filterBy.includes('contains')) {
- const filterMatch = filterBy.match(/contains\(([a-zA-Z\/]+),\s?'(.*?)'/);
+ const filterMatch = filterBy.match(/contains\(([a-zA-Z/]+),\s?'(.*?)'/);
const fieldName = filterMatch[1].trim();
columnFilters[fieldName] = { type: 'substring', term: filterMatch[2].trim() };
}
if (filterBy.includes('substringof')) {
- const filterMatch = filterBy.match(/substringof\('(.*?)',\s([a-zA-Z\/]+)/);
+ const filterMatch = filterBy.match(/substringof\('(.*?)',\s([a-zA-Z/]+)/);
const fieldName = filterMatch[2].trim();
columnFilters[fieldName] = { type: 'substring', term: filterMatch[1].trim() };
}
for (const operator of ['eq', 'ne', 'le', 'lt', 'gt', 'ge']) {
if (filterBy.includes(operator)) {
- const re = new RegExp(`([a-zA-Z ]*) ${operator} \'(.*?)\'`);
+ const re = new RegExp(`([a-zA-Z ]*) ${operator} '(.*?)'`);
const filterMatch = re.exec(filterBy);
if (Array.isArray(filterMatch)) {
const fieldName = filterMatch[1].trim();
@@ -383,6 +384,8 @@ export default class Example09 {
const gridStateChanges: GridStateChange = event.detail;
// console.log('Client sample, Grid State changed:: ', gridStateChanges);
console.log('Client sample, Grid State changed:: ', gridStateChanges.change);
+
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(gridStateChanges.gridState));
}
}
@@ -400,6 +403,10 @@ export default class Example09 {
]);
}
+ clearLocalStorage() {
+ localStorage.removeItem(STORAGE_KEY);
+ }
+
throwPageChangeError() {
this.isPageErrorTest = true;
this.sgb.paginationService.goToLastPage();
diff --git a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts
index a9e446a11..6c135a35c 100644
--- a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts
+++ b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts
@@ -1444,7 +1444,7 @@ describe('GridOdataService', () => {
const currentSorters = service.getCurrentSorters();
expect(query).toBe(expectation);
- expect(currentSorters).toEqual([{ columnId: 'Gender', direction: 'desc' }, { columnId: 'FirstName', direction: 'asc' }]);
+ expect(currentSorters).toEqual([{ columnId: 'gender', direction: 'desc' }, { columnId: 'firstName', direction: 'asc' }]);
});
it('should return a query string using a different field to query when the column has a "queryField" defined in its definition', () => {
@@ -1460,7 +1460,7 @@ describe('GridOdataService', () => {
const currentSorters = service.getCurrentSorters();
expect(query).toBe(expectation);
- expect(currentSorters).toEqual([{ columnId: 'Gender', direction: 'desc' }, { columnId: 'Name', direction: 'asc' }]);
+ expect(currentSorters).toEqual([{ columnId: 'gender', direction: 'desc' }, { columnId: 'name', direction: 'asc' }]);
});
it('should return a query string using a different field to query when the column has a "queryFieldSorter" defined in its definition', () => {
@@ -1476,7 +1476,7 @@ describe('GridOdataService', () => {
const currentSorters = service.getCurrentSorters();
expect(query).toBe(expectation);
- expect(currentSorters).toEqual([{ columnId: 'Gender', direction: 'desc' }, { columnId: 'Name', direction: 'asc' }]);
+ expect(currentSorters).toEqual([{ columnId: 'gender', direction: 'desc' }, { columnId: 'name', direction: 'asc' }]);
});
it('should return a query without the field sorter when its field property is missing', () => {
@@ -1492,7 +1492,7 @@ describe('GridOdataService', () => {
const currentSorters = service.getCurrentSorters();
expect(query).toBe(expectation);
- expect(currentSorters).toEqual([{ columnId: 'Gender', direction: 'desc' }, { columnId: 'FirstName', direction: 'asc' }]);
+ expect(currentSorters).toEqual([{ columnId: 'gender', direction: 'desc' }, { columnId: 'firstName', direction: 'asc' }]);
});
it('should return a query without any sorting after clearSorters was called', () => {
@@ -1546,7 +1546,7 @@ describe('GridOdataService', () => {
const currentSorters = service.getCurrentSorters();
expect(query).toBe(expectation);
- expect(currentSorters).toEqual([{ columnId: 'Gender', direction: 'desc' }, { columnId: 'FirstName', direction: 'asc' }]);
+ expect(currentSorters).toEqual([{ columnId: 'gender', direction: 'desc' }, { columnId: 'firstName', direction: 'asc' }]);
});
it('should return a query without any sorting after clearSorters was called but without pagination when "enablePagination" is set to False', () => {
diff --git a/packages/odata/src/services/grid-odata.service.ts b/packages/odata/src/services/grid-odata.service.ts
index 4af5d1377..f54cace12 100644
--- a/packages/odata/src/services/grid-odata.service.ts
+++ b/packages/odata/src/services/grid-odata.service.ts
@@ -543,12 +543,10 @@ export class GridOdataService implements BackendService {
queryField = titleCase(queryField);
}
- if (columnFieldName !== '') {
- currentSorters.push({
- columnId: columnFieldName,
- direction: columnDef.sortAsc ? 'asc' : 'desc'
- });
- }
+ currentSorters.push({
+ columnId: columnDef.sortCol.id,
+ direction: columnDef.sortAsc ? SortDirection.asc : SortDirection.desc
+ });
if (queryField !== '') {
odataSorters.push({
diff --git a/test/cypress/e2e/example09.cy.ts b/test/cypress/e2e/example09.cy.ts
index b00fa9035..ef670245f 100644
--- a/test/cypress/e2e/example09.cy.ts
+++ b/test/cypress/e2e/example09.cy.ts
@@ -1,3 +1,5 @@
+const STORAGE_KEY = 'slickgrid-universal-example09-gridstate';
+
describe('Example 09 - OData Grid', () => {
const GRID_ROW_HEIGHT = 45;
@@ -920,4 +922,31 @@ describe('Example 09 - OData Grid', () => {
});
});
+
+ describe('persistance', () => {
+ it('should persist sorting and re-apply on refresh', () => {
+ cy.get('[data-test=clear-local-storage]')
+ .click();
+
+ cy.get('.slick-header-columns')
+ .children('.slick-header-column:nth(1)')
+ .click();
+
+ cy.reload();
+
+ cy.window().its('localStorage').invoke('getItem', STORAGE_KEY)
+ .should('not.be.null');
+
+ cy.get('.slick-header-columns')
+ .children('.slick-header-column:nth(1)')
+ .find('.slick-sort-indicator.slick-sort-indicator-asc')
+ .should('be.visible');
+
+ cy.get('[data-test=clear-local-storage]')
+ .click();
+
+ cy.window().its('localStorage').invoke('getItem', STORAGE_KEY)
+ .should('be.null');
+ });
+ });
});