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

Commit fd31361

Browse files
committed
Merge branch 'master' into feat/tree-data-change-toggled-item
2 parents afb61cf + 4b10d01 commit fd31361

File tree

11 files changed

+1622
-972
lines changed

11 files changed

+1622
-972
lines changed

package.json

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,20 @@
7676
}
7777
},
7878
"dependencies": {
79-
"@slickgrid-universal/common": "^0.16.2",
80-
"@slickgrid-universal/custom-footer-component": "^0.16.2",
81-
"@slickgrid-universal/empty-warning-component": "^0.16.2",
82-
"@slickgrid-universal/event-pub-sub": "^0.16.2",
83-
"@slickgrid-universal/rxjs-observable": "^0.16.2",
79+
"@slickgrid-universal/common": "^0.17.0",
80+
"@slickgrid-universal/custom-footer-component": "^0.17.0",
81+
"@slickgrid-universal/empty-warning-component": "^0.17.0",
82+
"@slickgrid-universal/event-pub-sub": "^0.17.0",
83+
"@slickgrid-universal/rxjs-observable": "^0.17.0",
8484
"@types/dompurify": "^2.2.3",
8585
"@types/jquery": "^3.5.6",
8686
"dequal": "^2.0.2",
87-
"dompurify": "^2.3.0",
87+
"dompurify": "^2.3.1",
8888
"font-awesome": "^4.7.0",
8989
"jquery": "~3.5.1",
9090
"jquery-ui-dist": "^1.12.1",
9191
"moment-mini": "^2.24.0",
92-
"rxjs": "^7.2.0"
92+
"rxjs": "^7.3.0"
9393
},
9494
"peerDependencies": {
9595
"@angular/core": ">=12.1.2",
@@ -98,39 +98,39 @@
9898
"typescript": ">=4.3.5"
9999
},
100100
"devDependencies": {
101-
"@angular-devkit/build-angular": "~12.1.3",
102-
"@angular-eslint/builder": "12.3.1",
103-
"@angular-eslint/eslint-plugin": "12.3.1",
104-
"@angular-eslint/eslint-plugin-template": "12.3.1",
105-
"@angular-eslint/schematics": "12.3.1",
106-
"@angular-eslint/template-parser": "12.3.1",
107-
"@angular/animations": "^12.1.3",
108-
"@angular/cli": "^12.1.3",
109-
"@angular/common": "^12.1.3",
110-
"@angular/compiler": "^12.1.3",
111-
"@angular/compiler-cli": "^12.1.3",
112-
"@angular/core": "^12.1.3",
113-
"@angular/forms": "^12.1.3",
114-
"@angular/language-service": "^12.1.3",
115-
"@angular/platform-browser": "^12.1.3",
116-
"@angular/platform-browser-dynamic": "^12.1.3",
117-
"@angular/router": "^12.1.3",
101+
"@angular-devkit/build-angular": "~12.2.5",
102+
"@angular-eslint/builder": "12.4.1",
103+
"@angular-eslint/eslint-plugin": "12.4.1",
104+
"@angular-eslint/eslint-plugin-template": "12.4.1",
105+
"@angular-eslint/schematics": "12.4.1",
106+
"@angular-eslint/template-parser": "12.4.1",
107+
"@angular/animations": "^12.2.5",
108+
"@angular/cli": "^12.2.5",
109+
"@angular/common": "^12.2.5",
110+
"@angular/compiler": "^12.2.5",
111+
"@angular/compiler-cli": "^12.2.5",
112+
"@angular/core": "^12.2.5",
113+
"@angular/forms": "^12.2.5",
114+
"@angular/language-service": "^12.2.5",
115+
"@angular/platform-browser": "^12.2.5",
116+
"@angular/platform-browser-dynamic": "^12.2.5",
117+
"@angular/router": "^12.2.5",
118118
"@ng-select/ng-select": "^7.2.0",
119119
"@ngx-translate/core": "^13.0.0",
120120
"@ngx-translate/http-loader": "^6.0.0",
121-
"@slickgrid-universal/composite-editor-component": "^0.16.2",
122-
"@slickgrid-universal/excel-export": "^0.16.2",
123-
"@slickgrid-universal/graphql": "^0.16.2",
124-
"@slickgrid-universal/odata": "^0.16.2",
125-
"@slickgrid-universal/text-export": "^0.16.2",
121+
"@slickgrid-universal/composite-editor-component": "^0.17.0",
122+
"@slickgrid-universal/excel-export": "^0.17.0",
123+
"@slickgrid-universal/graphql": "^0.17.0",
124+
"@slickgrid-universal/odata": "^0.17.0",
125+
"@slickgrid-universal/text-export": "^0.17.0",
126126
"@types/flatpickr": "^3.1.2",
127-
"@types/jest": "^26.0.24",
127+
"@types/jest": "^27.0.1",
128128
"@types/moment": "^2.13.0",
129-
"@types/node": "^16.4.1",
129+
"@types/node": "^16.9.0",
130130
"@types/text-encoding-utf-8": "^1.0.2",
131-
"@typescript-eslint/eslint-plugin": "4.28.4",
132-
"@typescript-eslint/parser": "4.28.4",
133-
"autoprefixer": "^10.3.1",
131+
"@typescript-eslint/eslint-plugin": "4.31.0",
132+
"@typescript-eslint/parser": "4.31.0",
133+
"autoprefixer": "^10.3.4",
134134
"bootstrap": "^5.0.2",
135135
"codecov": "^3.8.3",
136136
"codelyzer": "^6.0.2",
@@ -140,29 +140,29 @@
140140
"custom-event-polyfill": "^1.0.7",
141141
"del": "^6.0.0",
142142
"del-cli": "^4.0.1",
143-
"eslint": "^7.31.0",
144-
"jest": "^27.0.6",
143+
"eslint": "^7.32.0",
144+
"jest": "^27.1.1",
145145
"jest-extended": "^0.11.5",
146-
"jest-preset-angular": "^9.0.5",
147-
"ng-packagr": "^12.1.2",
146+
"jest-preset-angular": "^9.0.7",
147+
"ng-packagr": "^12.2.1",
148148
"ngx-bootstrap": "^7.0.0",
149149
"npm-run-all": "^4.1.5",
150150
"postcss": "^8.3.6",
151151
"postcss-cli": "^8.3.1",
152152
"require-dir": "^1.2.0",
153153
"rimraf": "^3.0.2",
154154
"run-sequence": "^2.2.1",
155-
"sass": "^1.36.0",
155+
"sass": "^1.39.0",
156156
"standard-version": "^9.3.1",
157157
"stream-browserify": "^3.0.0",
158-
"ts-node": "^10.1.0",
159-
"tslib": "^2.3.0",
158+
"ts-node": "^10.2.1",
159+
"tslib": "^2.3.1",
160160
"typescript": "~4.3.5",
161-
"yargs": "^17.0.1",
161+
"yargs": "^17.1.1",
162162
"zone.js": "~0.11.4"
163163
},
164164
"engines": {
165165
"node": ">=14.15.0",
166166
"npm": ">=6.14.8"
167167
}
168-
}
168+
}

src/app/examples/grid-editor.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
AutocompleteOption,
88
Column,
99
Editors,
10-
EditorArgs,
10+
EditorArguments,
1111
EditorValidator,
1212
FieldType,
1313
Filters,
@@ -34,7 +34,7 @@ const URL_COUNTRIES_COLLECTION = 'assets/data/countries.json';
3434
const URL_COUNTRY_NAMES = 'assets/data/country_names.json';
3535

3636
// you can create custom validator to pass to an inline editor
37-
const myCustomTitleValidator: EditorValidator = (value: any, args?: EditorArgs) => {
37+
const myCustomTitleValidator: EditorValidator = (value: any, args?: EditorArguments) => {
3838
// you can get the Editor Args which can be helpful, e.g. we can get the Translate Service from it
3939
const grid = args && args.grid;
4040
const gridOptions = (grid?.getOptions?.() ?? {}) as GridOption;

src/app/examples/grid-odata.component.html

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ <h2>
99
</a>
1010
</span>
1111
</h2>
12-
<div class="subtitle" [innerHTML]="subTitle"></div>
12+
<div class="row">
13+
<div class="col-sm-9">
14+
<div class="subtitle" [innerHTML]="subTitle"></div>
15+
</div>
16+
<div class="col-sm-3">
17+
<div class="alert alert-danger" *ngIf="errorStatus" data-test="error-status">
18+
<em><strong>Backend Error:</strong> <span [innerHTML]="errorStatus"></span></em>
19+
</div>
20+
</div>
21+
</div>
1322

1423
<div class="row">
1524
<div class="col-sm-4">
@@ -53,6 +62,13 @@ <h2>
5362
(click)="changeCountEnableFlag()">
5463
<span style="font-weight: bold">Enable Count</span> (add to OData query)
5564
</label>
65+
<span class="float-end">
66+
<button class="btn btn-outline-danger btn-sm " data-test="throw-page-error-btn"
67+
(click)="throwPageChangeError()">
68+
<span>Throw Error Going to Last Page... </span>
69+
<i class="mdi mdi-page-last"></i>
70+
</button>
71+
</span>
5672
</div>
5773
</div>
5874
<div class="row">
@@ -72,7 +88,10 @@ <h2>
7288
[gridOptions]="gridOptions"
7389
[paginationOptions]="paginationOptions"
7490
[dataset]="dataset"
91+
(onAngularGridCreated)="angularGridReady($event.detail)"
7592
(onGridStateChanged)="gridStateChanged($event.detail)"
76-
(onAngularGridCreated)="angularGridReady($event.detail)">
93+
(onBeforeSort)="handleOnBeforeSort($event)"
94+
(onBeforeSearchChange)="handleOnBeforeSearchChange($event)"
95+
(onBeforePaginationChange)="handleOnBeforePaginationChange($event)">
7796
</angular-slickgrid>
7897
</div>

src/app/examples/grid-odata.component.ts

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ export class GridOdataComponent implements OnInit {
3434
</ul>
3535
<li>OData Service could be replaced by other Service type in the future (GraphQL or whichever you provide)</li>
3636
<li>You can also preload a grid with certain "presets" like Filters / Sorters / Pagination <a href="https://github.com/ghiscoding/Angular-Slickgrid/wiki/Grid-State-&-Preset" target="_blank">Wiki - Grid Preset</a>
37+
<li><span class="text-danger">NOTE:</span> For demo purposes, the last column (filter & sort) will always throw an
38+
error and its only purpose is to demo what would happen when you encounter a backend server error
39+
(the UI should rollback to previous state before you did the action).
40+
Also changing Page Size to 50,000 will also throw which again is for demo purposes.
41+
</li>
3742
</ul>
3843
`;
3944
angularGrid!: AngularGridInstance;
@@ -47,6 +52,8 @@ export class GridOdataComponent implements OnInit {
4752
odataVersion = 2;
4853
odataQuery = '';
4954
processing = true;
55+
errorStatus = '';
56+
isPageErrorTest = false;
5057
status = { text: 'processing...', class: 'alert alert-danger' };
5158

5259
constructor(private readonly cd: ChangeDetectorRef, private http: HttpClient) { }
@@ -72,7 +79,7 @@ export class GridOdataComponent implements OnInit {
7279
collection: [{ value: '', label: '' }, { value: 'male', label: 'male' }, { value: 'female', label: 'female' }]
7380
}
7481
},
75-
{ id: 'company', name: 'Company', field: 'company' },
82+
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true },
7683
];
7784

7885
this.gridOptions = {
@@ -92,7 +99,7 @@ export class GridOdataComponent implements OnInit {
9299
enableRowSelection: true,
93100
enablePagination: true, // you could optionally disable the Pagination
94101
pagination: {
95-
pageSizes: [10, 15, 20, 25, 30, 40, 50, 75, 100],
102+
pageSizes: [10, 20, 50, 100, 500, 50000],
96103
pageSize: defaultPageSize,
97104
totalItems: 0
98105
},
@@ -113,7 +120,14 @@ export class GridOdataComponent implements OnInit {
113120
enableCount: this.isCountEnabled, // add the count in the OData query, which will return a property named "odata.count" (v2) or "@odata.count" (v4)
114121
version: this.odataVersion // defaults to 2, the query string is slightly different between OData 2 and 4
115122
},
116-
preProcess: () => this.displaySpinner(true),
123+
onError: (error: Error) => {
124+
this.errorStatus = error.message;
125+
this.displaySpinner(false, true);
126+
},
127+
preProcess: () => {
128+
this.errorStatus = '';
129+
this.displaySpinner(true);
130+
},
117131
process: (query) => this.getCustomerApiCall(query),
118132
postProcess: (response) => {
119133
this.metrics = response.metrics;
@@ -125,11 +139,15 @@ export class GridOdataComponent implements OnInit {
125139
};
126140
}
127141

128-
displaySpinner(isProcessing: boolean) {
142+
displaySpinner(isProcessing: boolean, isError?: boolean) {
129143
this.processing = isProcessing;
130-
this.status = (isProcessing)
131-
? { text: 'processing...', class: 'alert alert-danger' }
132-
: { text: 'done', class: 'alert alert-success' };
144+
if (isError) {
145+
this.status = { text: 'ERROR!!!', class: 'alert alert-danger' };
146+
} else {
147+
this.status = (isProcessing)
148+
? { text: 'loading...', class: 'alert alert-warning' }
149+
: { text: 'finished', class: 'alert alert-success' };
150+
}
133151
}
134152

135153
getCustomerCallback(data: any) {
@@ -180,7 +198,7 @@ export class GridOdataComponent implements OnInit {
180198
/** This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
181199
* in your case the getCustomer() should be a WebAPI function returning a Promise
182200
*/
183-
getCustomerDataApiMock(query: string) {
201+
getCustomerDataApiMock(query: string): Promise<any> {
184202
// the mock is returning a Promise, just like a WebAPI typically does
185203
return new Promise((resolve, reject) => {
186204
const queryParams = query.toLowerCase().split('&');
@@ -190,9 +208,17 @@ export class GridOdataComponent implements OnInit {
190208
let countTotalItems = 100;
191209
const columnFilters = {};
192210

211+
if (this.isPageErrorTest) {
212+
this.isPageErrorTest = false;
213+
throw new Error('Server timed out trying to retrieve data for the last page');
214+
}
215+
193216
for (const param of queryParams) {
194217
if (param.includes('$top=')) {
195218
top = +(param.substring('$top='.length));
219+
if (top === 50000) {
220+
throw new Error('Server timed out retrieving 50,000 rows');
221+
}
196222
}
197223
if (param.includes('$skip=')) {
198224
skip = +(param.substring('$skip='.length));
@@ -229,9 +255,19 @@ export class GridOdataComponent implements OnInit {
229255
const fieldName = filterMatch![1].trim();
230256
(columnFilters as any)[fieldName] = { type: 'ends', term: filterMatch![2].trim() };
231257
}
258+
259+
// simular a backend error when trying to sort on the "Company" field
260+
if (filterBy.includes('company')) {
261+
throw new Error('Server could not filter using the field "Company"');
262+
}
232263
}
233264
}
234265

266+
// simular a backend error when trying to sort on the "Company" field
267+
if (orderBy.includes('company')) {
268+
throw new Error('Server could not sort using the field "Company"');
269+
}
270+
235271
const sort = orderBy.includes('asc')
236272
? 'ASC'
237273
: orderBy.includes('desc')
@@ -303,6 +339,31 @@ export class GridOdataComponent implements OnInit {
303339
console.log('Client sample, Grid State changed:: ', gridStateChanges.change);
304340
}
305341

342+
throwPageChangeError() {
343+
this.isPageErrorTest = true;
344+
this.angularGrid?.paginationService?.goToLastPage();
345+
}
346+
347+
// YOU CAN CHOOSE TO PREVENT EVENT FROM BUBBLING IN THE FOLLOWING 3x EVENTS
348+
// note however that internally the cancelling the search is more of a rollback
349+
handleOnBeforeSort(e: Event) {
350+
// e.preventDefault();
351+
// return false;
352+
return true;
353+
}
354+
355+
handleOnBeforeSearchChange(e: Event) {
356+
// e.preventDefault();
357+
// return false;
358+
return true;
359+
}
360+
361+
handleOnBeforePaginationChange(e: Event) {
362+
// e.preventDefault();
363+
// return false;
364+
return true;
365+
}
366+
306367
// THE FOLLOWING METHODS ARE ONLY FOR DEMO PURPOSES DO NOT USE THIS CODE
307368
// ---
308369

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ const mockDataView = {
209209
destroy: jest.fn(),
210210
beginUpdate: jest.fn(),
211211
endUpdate: jest.fn(),
212+
getFilteredItemCount: jest.fn(),
212213
getItem: jest.fn(),
213214
getItems: jest.fn(),
214215
getItemCount: jest.fn(),
@@ -1839,6 +1840,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
18391840
totalItemCount: 2
18401841
};
18411842
jest.spyOn(mockDataView, 'getItemCount').mockReturnValue(mockData.length);
1843+
jest.spyOn(mockDataView, 'getFilteredItemCount').mockReturnValue(mockData.length);
18421844

18431845
component.gridOptions = { enablePagination: false, showCustomFooter: true };
18441846
component.initialization(slickEventHandler);
@@ -1854,10 +1856,10 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
18541856
const expectation = {
18551857
startTime: expect.toBeDate(),
18561858
endTime: expect.toBeDate(),
1857-
itemCount: 2,
1859+
itemCount: 0,
18581860
totalItemCount: 0
18591861
};
1860-
jest.spyOn(mockDataView, 'getLength').mockReturnValue(2);
1862+
jest.spyOn(mockDataView, 'getFilteredItemCount').mockReturnValue(0);
18611863

18621864
component.gridOptions = { enablePagination: false, showCustomFooter: true };
18631865
component.initialization(slickEventHandler);
@@ -1885,6 +1887,7 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
18851887

18861888
component.gridOptions.enableCheckboxSelector = true;
18871889
component.gridOptions.presets = { rowSelection: { dataContextIds: selectedRowIds } };
1890+
component.isDatasetInitialized = false;
18881891
component.initialization(slickEventHandler);
18891892
component.dataset = mockData;
18901893

0 commit comments

Comments
 (0)