angular-slickgrid 4.1.4 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +12 -0
- package/.codecov.yml +17 -0
- package/.editorconfig +18 -0
- package/.eslintrc.json +50 -0
- package/.github/CODE_OF_CONDUCT.md +76 -0
- package/.github/FUNDING.yml +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +54 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +44 -0
- package/.github/renovate.json5 +26 -0
- package/.github/stale.yml +7 -0
- package/.github/workflows/main.yml +83 -0
- package/.vscode/extensions.json +9 -0
- package/.vscode/launch.json +72 -0
- package/.vscode/settings.json +7 -0
- package/.vscode/tasks.json +77 -0
- package/CHANGELOG.md +1172 -0
- package/LICENSE +20 -20
- package/README.md +182 -180
- package/angular.json +148 -0
- package/dist/LICENSE +20 -0
- package/dist/README.md +182 -0
- package/{angular-slickgrid.d.ts → dist/angular-slickgrid.d.ts} +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/constants.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/extensions/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/extensions/slickRowDetailView.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/global-grid-options.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/angularComponentOutput.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/externalTestingDependencies.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/gridOption.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/rowDetailView.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/slickGrid.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/angularUtil.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/bsDropdown.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/container.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/translater.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/utilities.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/slickgrid-config.d.ts +0 -0
- package/{esm2020 → dist/esm2020}/angular-slickgrid.mjs +0 -0
- package/dist/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1171 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/constants.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +2 -2
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/global-grid-options.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs +1 -1
- package/dist/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +2 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/index.mjs +1 -1
- package/dist/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +2 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +5 -5
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/angularUtil.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/container.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/translater.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/utilities.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/slickgrid-config.mjs +1 -1
- package/{esm2020 → dist/esm2020}/public_api.mjs +1 -1
- package/{fesm2015 → dist/fesm2015}/angular-slickgrid.mjs +25 -22
- package/dist/fesm2015/angular-slickgrid.mjs.map +1 -0
- package/{fesm2020 → dist/fesm2020}/angular-slickgrid.mjs +25 -22
- package/dist/fesm2020/angular-slickgrid.mjs.map +1 -0
- package/{i18n → dist/i18n}/en.json +89 -89
- package/{i18n → dist/i18n}/fr.json +90 -90
- package/dist/package.json +79 -0
- package/{public_api.d.ts → dist/public_api.d.ts} +0 -0
- package/global.d.ts +1 -0
- package/ngcc.config.js +13 -0
- package/package.json +121 -37
- package/screenshots/column-picker.png +0 -0
- package/screenshots/composite-editor.png +0 -0
- package/screenshots/draggable-grouping.png +0 -0
- package/screenshots/editors.png +0 -0
- package/screenshots/export-to-file.png +0 -0
- package/screenshots/filter_and_sort.png +0 -0
- package/screenshots/formatters.png +0 -0
- package/screenshots/frozen.png +0 -0
- package/screenshots/multipleSelectFilter.png +0 -0
- package/screenshots/pagination.png +0 -0
- package/screenshots/selectFilter.png +0 -0
- package/screenshots/singleFilter.png +0 -0
- package/src/app/app-routing.module.ts +83 -0
- package/src/app/app.component.html +160 -0
- package/src/app/app.component.scss +65 -0
- package/src/app/app.component.ts +10 -0
- package/src/app/app.module.ts +175 -0
- package/src/app/examples/custom-angularComponentEditor.ts +184 -0
- package/src/app/examples/custom-angularComponentFilter.ts +126 -0
- package/src/app/examples/custom-inputEditor.ts +124 -0
- package/src/app/examples/custom-inputFilter.ts +142 -0
- package/src/app/examples/custom-titleFormatter.component.ts +8 -0
- package/src/app/examples/editor-ng-select.component.ts +37 -0
- package/src/app/examples/filter-ng-select.component.ts +32 -0
- package/src/app/examples/grid-additem.component.html +48 -0
- package/src/app/examples/grid-additem.component.ts +272 -0
- package/src/app/examples/grid-angular.component.html +79 -0
- package/src/app/examples/grid-angular.component.scss +28 -0
- package/src/app/examples/grid-angular.component.ts +370 -0
- package/src/app/examples/grid-autoheight.component.html +52 -0
- package/src/app/examples/grid-autoheight.component.ts +147 -0
- package/src/app/examples/grid-basic.component.html +29 -0
- package/src/app/examples/grid-basic.component.ts +82 -0
- package/src/app/examples/grid-clientside.component.html +51 -0
- package/src/app/examples/grid-clientside.component.ts +293 -0
- package/src/app/examples/grid-colspan.component.html +39 -0
- package/src/app/examples/grid-colspan.component.scss +11 -0
- package/src/app/examples/grid-colspan.component.ts +155 -0
- package/src/app/examples/grid-composite-editor.component.html +79 -0
- package/src/app/examples/grid-composite-editor.component.scss +19 -0
- package/src/app/examples/grid-composite-editor.component.ts +948 -0
- package/src/app/examples/grid-contextmenu.component.html +62 -0
- package/src/app/examples/grid-contextmenu.component.scss +44 -0
- package/src/app/examples/grid-contextmenu.component.ts +473 -0
- package/src/app/examples/grid-custom-tooltip.component.html +25 -0
- package/src/app/examples/grid-custom-tooltip.component.scss +77 -0
- package/src/app/examples/grid-custom-tooltip.component.ts +483 -0
- package/src/app/examples/grid-draggrouping.component.html +93 -0
- package/src/app/examples/grid-draggrouping.component.ts +397 -0
- package/src/app/examples/grid-editor.component.html +88 -0
- package/src/app/examples/grid-editor.component.ts +699 -0
- package/src/app/examples/grid-formatter.component.html +26 -0
- package/src/app/examples/grid-formatter.component.ts +162 -0
- package/src/app/examples/grid-frozen.component.html +65 -0
- package/src/app/examples/grid-frozen.component.scss +11 -0
- package/src/app/examples/grid-frozen.component.ts +303 -0
- package/src/app/examples/grid-graphql-nopage.component.html +33 -0
- package/src/app/examples/grid-graphql-nopage.component.scss +9 -0
- package/src/app/examples/grid-graphql-nopage.component.ts +242 -0
- package/src/app/examples/grid-graphql.component.html +87 -0
- package/src/app/examples/grid-graphql.component.ts +304 -0
- package/src/app/examples/grid-grouping.component.html +80 -0
- package/src/app/examples/grid-grouping.component.ts +313 -0
- package/src/app/examples/grid-headerbutton.component.html +31 -0
- package/src/app/examples/grid-headerbutton.component.scss +10 -0
- package/src/app/examples/grid-headerbutton.component.ts +233 -0
- package/src/app/examples/grid-headermenu.component.html +31 -0
- package/src/app/examples/grid-headermenu.component.scss +25 -0
- package/src/app/examples/grid-headermenu.component.ts +159 -0
- package/src/app/examples/grid-localization.component.html +54 -0
- package/src/app/examples/grid-localization.component.ts +293 -0
- package/src/app/examples/grid-menu.component.html +37 -0
- package/src/app/examples/grid-menu.component.scss +28 -0
- package/src/app/examples/grid-menu.component.ts +229 -0
- package/src/app/examples/grid-odata.component.html +116 -0
- package/src/app/examples/grid-odata.component.ts +441 -0
- package/src/app/examples/grid-range.component.html +74 -0
- package/src/app/examples/grid-range.component.ts +291 -0
- package/src/app/examples/grid-remote.component.html +37 -0
- package/src/app/examples/grid-remote.component.ts +153 -0
- package/src/app/examples/grid-resize-by-content.component.html +62 -0
- package/src/app/examples/grid-resize-by-content.component.scss +19 -0
- package/src/app/examples/grid-resize-by-content.component.ts +780 -0
- package/src/app/examples/grid-rowdetail.component.html +35 -0
- package/src/app/examples/grid-rowdetail.component.ts +205 -0
- package/src/app/examples/grid-rowmove.component.html +49 -0
- package/src/app/examples/grid-rowmove.component.ts +234 -0
- package/src/app/examples/grid-rowselection.component.html +76 -0
- package/src/app/examples/grid-rowselection.component.ts +267 -0
- package/src/app/examples/grid-state.component.html +36 -0
- package/src/app/examples/grid-state.component.ts +259 -0
- package/src/app/examples/grid-tabs.component.html +35 -0
- package/src/app/examples/grid-tabs.component.ts +115 -0
- package/src/app/examples/grid-trading.component.html +58 -0
- package/src/app/examples/grid-trading.component.scss +49 -0
- package/src/app/examples/grid-trading.component.ts +319 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.html +79 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.scss +47 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.ts +311 -0
- package/src/app/examples/grid-tree-data-parent-child.component.html +108 -0
- package/src/app/examples/grid-tree-data-parent-child.component.scss +10 -0
- package/src/app/examples/grid-tree-data-parent-child.component.ts +351 -0
- package/src/app/examples/home.component.html +41 -0
- package/src/app/examples/home.component.ts +9 -0
- package/src/app/examples/rowdetail-preload.component.ts +10 -0
- package/src/app/examples/rowdetail-view.component.html +36 -0
- package/src/app/examples/rowdetail-view.component.ts +54 -0
- package/src/app/examples/swt-common-grid-pagination.component.ts +156 -0
- package/src/app/examples/swt-common-grid-test.component.html +30 -0
- package/src/app/examples/swt-common-grid-test.component.ts +219 -0
- package/src/app/examples/swt-common-grid.component.ts +436 -0
- package/src/app/examples/swt-logger.service.ts +165 -0
- package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.html +4 -0
- package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts +1395 -0
- package/src/app/modules/angular-slickgrid/constants.ts +97 -0
- package/src/app/modules/angular-slickgrid/extensions/index.ts +1 -0
- package/src/app/modules/angular-slickgrid/extensions/slickRowDetailView.ts +375 -0
- package/src/app/modules/angular-slickgrid/global-grid-options.ts +245 -0
- package/src/app/modules/angular-slickgrid/index.ts +11 -0
- package/src/app/modules/angular-slickgrid/models/angularComponentOutput.interface.ts +6 -0
- package/src/app/modules/angular-slickgrid/models/angularGridInstance.interface.ts +68 -0
- package/src/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.ts +37 -0
- package/src/app/modules/angular-slickgrid/models/gridOption.interface.ts +12 -0
- package/src/app/modules/angular-slickgrid/models/index.ts +6 -0
- package/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts +33 -0
- package/src/app/modules/angular-slickgrid/models/slickGrid.interface.ts +7 -0
- package/src/app/modules/angular-slickgrid/modules/angular-slickgrid.module.ts +37 -0
- package/src/app/modules/angular-slickgrid/services/angularUtil.service.ts +48 -0
- package/src/app/modules/angular-slickgrid/services/bsDropdown.service.ts +142 -0
- package/src/app/modules/angular-slickgrid/services/container.service.ts +24 -0
- package/src/app/modules/angular-slickgrid/services/index.ts +5 -0
- package/src/app/modules/angular-slickgrid/services/translater.service.ts +38 -0
- package/src/app/modules/angular-slickgrid/services/utilities.ts +19 -0
- package/src/app/modules/angular-slickgrid/slickgrid-config.ts +10 -0
- package/src/app/slickgrid-custom-variables.scss +10 -0
- package/src/assets/.gitkeep +0 -0
- package/src/assets/data/collection_100_numbers.json +12 -0
- package/src/assets/data/collection_500_numbers.json +52 -0
- package/src/assets/data/countries.json +245 -0
- package/src/assets/data/country_names.json +245 -0
- package/src/assets/data/customers_100.json +102 -0
- package/src/assets/i18n/en.json +90 -0
- package/src/assets/i18n/fr.json +91 -0
- package/src/environments/environment.prod.ts +3 -0
- package/src/environments/environment.ts +8 -0
- package/src/favicon.ico +0 -0
- package/src/index.html +18 -0
- package/src/main.ts +13 -0
- package/src/polyfills.ts +52 -0
- package/src/public_api.ts +1 -0
- package/src/styles.scss +66 -0
- package/src/typings.d.ts +10 -0
- package/tsconfig.app.json +25 -0
- package/tsconfig.json +40 -0
- package/tsconfig.spec.json +23 -0
- package/docs/assets/lib/multiple-select/README.md +0 -17
- package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +0 -1168
- package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +0 -2
- package/fesm2015/angular-slickgrid.mjs.map +0 -1
- package/fesm2020/angular-slickgrid.mjs.map +0 -1
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { GridOdataService, OdataServiceApi, OdataOption } from '@slickgrid-universal/odata';
|
|
3
|
+
import { ChangeDetectorRef, Component, OnInit, } from '@angular/core';
|
|
4
|
+
import { HttpClient } from '@angular/common/http';
|
|
5
|
+
import {
|
|
6
|
+
AngularGridInstance,
|
|
7
|
+
Column,
|
|
8
|
+
FieldType,
|
|
9
|
+
Filters,
|
|
10
|
+
GridOption,
|
|
11
|
+
GridStateChange,
|
|
12
|
+
Metrics,
|
|
13
|
+
OperatorType,
|
|
14
|
+
Pagination,
|
|
15
|
+
} from './../modules/angular-slickgrid';
|
|
16
|
+
|
|
17
|
+
const defaultPageSize = 20;
|
|
18
|
+
const sampleDataRoot = 'assets/data';
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
templateUrl: './grid-odata.component.html'
|
|
22
|
+
})
|
|
23
|
+
export class GridOdataComponent implements OnInit {
|
|
24
|
+
title = 'Example 5: Grid connected to Backend Server with OData';
|
|
25
|
+
subTitle = `
|
|
26
|
+
Sorting/Paging connected to a Backend OData Service (<a href="https://github.com/ghiscoding/Angular-Slickgrid/wiki/OData" target="_blank">Wiki docs</a>).
|
|
27
|
+
<br/>
|
|
28
|
+
<ul class="small">
|
|
29
|
+
<li>Only "Name" field is sortable for the demo (because we use JSON files), however "multiColumnSort: true" is also supported</li>
|
|
30
|
+
<li>This example also demos the Grid State feature, open the console log to see the changes</li>
|
|
31
|
+
<li>String column also support operator (>, >=, <, <=, <>, !=, =, ==, *)
|
|
32
|
+
<ul>
|
|
33
|
+
<li>The (*) can be used as startsWith (ex.: "abc*" => startsWith "abc") / endsWith (ex.: "*xyz" => endsWith "xyz")</li>
|
|
34
|
+
<li>The other operators can be used on column type number for example: ">=100" (bigger or equal than 100)</li>
|
|
35
|
+
</ul>
|
|
36
|
+
<li>OData Service could be replaced by other Service type in the future (GraphQL or whichever you provide)</li>
|
|
37
|
+
<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>
|
|
38
|
+
<li><span class="text-danger">NOTE:</span> For demo purposes, the last column (filter & sort) will always throw an
|
|
39
|
+
error and its only purpose is to demo what would happen when you encounter a backend server error
|
|
40
|
+
(the UI should rollback to previous state before you did the action).
|
|
41
|
+
Also changing Page Size to 50,000 will also throw which again is for demo purposes.
|
|
42
|
+
</li>
|
|
43
|
+
</ul>
|
|
44
|
+
`;
|
|
45
|
+
angularGrid!: AngularGridInstance;
|
|
46
|
+
columnDefinitions!: Column[];
|
|
47
|
+
gridOptions!: GridOption;
|
|
48
|
+
dataset = [];
|
|
49
|
+
metrics!: Metrics;
|
|
50
|
+
paginationOptions!: Pagination;
|
|
51
|
+
|
|
52
|
+
isCountEnabled = true;
|
|
53
|
+
isSelectEnabled = false;
|
|
54
|
+
isExpandEnabled = false;
|
|
55
|
+
odataVersion = 2;
|
|
56
|
+
odataQuery = '';
|
|
57
|
+
processing = true;
|
|
58
|
+
errorStatus = '';
|
|
59
|
+
isPageErrorTest = false;
|
|
60
|
+
status = { text: 'processing...', class: 'alert alert-danger' };
|
|
61
|
+
|
|
62
|
+
constructor(private readonly cd: ChangeDetectorRef, private http: HttpClient) { }
|
|
63
|
+
|
|
64
|
+
angularGridReady(angularGrid: AngularGridInstance) {
|
|
65
|
+
this.angularGrid = angularGrid;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
ngOnInit(): void {
|
|
69
|
+
this.columnDefinitions = [
|
|
70
|
+
{
|
|
71
|
+
id: 'name', name: 'Name', field: 'name', sortable: true,
|
|
72
|
+
type: FieldType.string,
|
|
73
|
+
filterable: true,
|
|
74
|
+
filter: {
|
|
75
|
+
model: Filters.compoundInput
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'gender', name: 'Gender', field: 'gender', filterable: true, sortable: true,
|
|
80
|
+
filter: {
|
|
81
|
+
model: Filters.singleSelect,
|
|
82
|
+
collection: [{ value: '', label: '' }, { value: 'male', label: 'male' }, { value: 'female', label: 'female' }]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true },
|
|
86
|
+
{ id: 'category_name', name: 'Category', field: 'category/name', filterable: true, sortable: true },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
this.gridOptions = {
|
|
90
|
+
enableAutoResize: true,
|
|
91
|
+
autoResize: {
|
|
92
|
+
container: '#demo-container',
|
|
93
|
+
rightPadding: 10
|
|
94
|
+
},
|
|
95
|
+
checkboxSelector: {
|
|
96
|
+
// you can toggle these 2 properties to show the "select all" checkbox in different location
|
|
97
|
+
hideInFilterHeaderRow: false,
|
|
98
|
+
hideInColumnTitleRow: true
|
|
99
|
+
},
|
|
100
|
+
enableCellNavigation: true,
|
|
101
|
+
enableFiltering: true,
|
|
102
|
+
enableCheckboxSelector: true,
|
|
103
|
+
enableRowSelection: true,
|
|
104
|
+
enablePagination: true, // you could optionally disable the Pagination
|
|
105
|
+
pagination: {
|
|
106
|
+
pageSizes: [10, 20, 50, 100, 500, 50000],
|
|
107
|
+
pageSize: defaultPageSize,
|
|
108
|
+
totalItems: 0
|
|
109
|
+
},
|
|
110
|
+
presets: {
|
|
111
|
+
// you can also type operator as string, e.g.: operator: 'EQ'
|
|
112
|
+
filters: [
|
|
113
|
+
{ columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
|
|
114
|
+
],
|
|
115
|
+
sorters: [
|
|
116
|
+
// direction can be written as 'asc' (uppercase or lowercase) and/or use the SortDirection type
|
|
117
|
+
{ columnId: 'name', direction: 'asc' }
|
|
118
|
+
],
|
|
119
|
+
pagination: { pageNumber: 2, pageSize: defaultPageSize }
|
|
120
|
+
},
|
|
121
|
+
backendServiceApi: {
|
|
122
|
+
service: new GridOdataService(),
|
|
123
|
+
options: {
|
|
124
|
+
enableCount: this.isCountEnabled, // add the count in the OData query, which will return a property named "__count" (v2) or "@odata.count" (v4)
|
|
125
|
+
enableSelect: this.isSelectEnabled,
|
|
126
|
+
enableExpand: this.isExpandEnabled,
|
|
127
|
+
version: this.odataVersion // defaults to 2, the query string is slightly different between OData 2 and 4
|
|
128
|
+
},
|
|
129
|
+
onError: (error: Error) => {
|
|
130
|
+
this.errorStatus = error.message;
|
|
131
|
+
this.displaySpinner(false, true);
|
|
132
|
+
},
|
|
133
|
+
preProcess: () => {
|
|
134
|
+
this.errorStatus = '';
|
|
135
|
+
this.displaySpinner(true);
|
|
136
|
+
},
|
|
137
|
+
process: (query) => this.getCustomerApiCall(query),
|
|
138
|
+
postProcess: (response) => {
|
|
139
|
+
this.metrics = response.metrics;
|
|
140
|
+
this.displaySpinner(false);
|
|
141
|
+
this.getCustomerCallback(response);
|
|
142
|
+
this.cd.detectChanges();
|
|
143
|
+
}
|
|
144
|
+
} as OdataServiceApi
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
displaySpinner(isProcessing: boolean, isError?: boolean) {
|
|
149
|
+
this.processing = isProcessing;
|
|
150
|
+
if (isError) {
|
|
151
|
+
this.status = { text: 'ERROR!!!', class: 'alert alert-danger' };
|
|
152
|
+
} else {
|
|
153
|
+
this.status = (isProcessing)
|
|
154
|
+
? { text: 'loading', class: 'alert alert-warning' }
|
|
155
|
+
: { text: 'finished', class: 'alert alert-success' };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
getCustomerCallback(data: any) {
|
|
160
|
+
// totalItems property needs to be filled for pagination to work correctly
|
|
161
|
+
// however we need to force Angular to do a dirty check, doing a clone object will do just that
|
|
162
|
+
let totalItemCount: number = data['totalRecordCount']; // you can use "totalRecordCount" or any name or "odata.count" when "enableCount" is set
|
|
163
|
+
if (this.isCountEnabled) {
|
|
164
|
+
totalItemCount = (this.odataVersion === 4) ? data['@odata.count'] : data['d']['__count'];
|
|
165
|
+
}
|
|
166
|
+
if (this.metrics) {
|
|
167
|
+
this.metrics.totalItemCount = totalItemCount;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// once pagination totalItems is filled, we can update the dataset
|
|
171
|
+
this.paginationOptions = { ...this.gridOptions.pagination, totalItems: totalItemCount } as Pagination;
|
|
172
|
+
this.dataset = this.odataVersion === 4 ? data.value : data.d.results;
|
|
173
|
+
this.odataQuery = data['query'];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
getCustomerApiCall(query: string) {
|
|
177
|
+
// in your case, you will call your WebAPI function (wich needs to return a Promise)
|
|
178
|
+
// for the demo purpose, we will call a mock WebAPI function
|
|
179
|
+
return this.getCustomerDataApiMock(query);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
goToFirstPage() {
|
|
183
|
+
this.angularGrid.paginationService!.goToFirstPage();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
goToLastPage() {
|
|
187
|
+
this.angularGrid.paginationService!.goToLastPage();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
setFiltersDynamically() {
|
|
191
|
+
// we can Set Filters Dynamically (or different filters) afterward through the FilterService
|
|
192
|
+
this.angularGrid.filterService.updateFilters([
|
|
193
|
+
// { columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
|
|
194
|
+
{ columnId: 'name', searchTerms: ['A'], operator: 'a*' },
|
|
195
|
+
]);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
setSortingDynamically() {
|
|
199
|
+
this.angularGrid.sortService.updateSorting([
|
|
200
|
+
{ columnId: 'name', direction: 'DESC' },
|
|
201
|
+
]);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
|
|
205
|
+
* in your case the getCustomer() should be a WebAPI function returning a Promise
|
|
206
|
+
*/
|
|
207
|
+
getCustomerDataApiMock(query: string): Promise<any> {
|
|
208
|
+
// the mock is returning a Promise, just like a WebAPI typically does
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const queryParams = query.toLowerCase().split('&');
|
|
211
|
+
let top: number;
|
|
212
|
+
let skip = 0;
|
|
213
|
+
let orderBy = '';
|
|
214
|
+
let countTotalItems = 100;
|
|
215
|
+
const columnFilters = {};
|
|
216
|
+
|
|
217
|
+
if (this.isPageErrorTest) {
|
|
218
|
+
this.isPageErrorTest = false;
|
|
219
|
+
throw new Error('Server timed out trying to retrieve data for the last page');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
for (const param of queryParams) {
|
|
223
|
+
if (param.includes('$top=')) {
|
|
224
|
+
top = +(param.substring('$top='.length));
|
|
225
|
+
if (top === 50000) {
|
|
226
|
+
throw new Error('Server timed out retrieving 50,000 rows');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (param.includes('$skip=')) {
|
|
230
|
+
skip = +(param.substring('$skip='.length));
|
|
231
|
+
}
|
|
232
|
+
if (param.includes('$orderby=')) {
|
|
233
|
+
orderBy = param.substring('$orderby='.length);
|
|
234
|
+
}
|
|
235
|
+
if (param.includes('$filter=')) {
|
|
236
|
+
const filterBy = param.substring('$filter='.length).replace('%20', ' ');
|
|
237
|
+
if (filterBy.includes('contains')) {
|
|
238
|
+
const filterMatch = filterBy.match(/contains\(([a-zA-Z\/]+),\s?'(.*?)'/);
|
|
239
|
+
const fieldName = filterMatch![1].trim();
|
|
240
|
+
(columnFilters as any)[fieldName] = { type: 'substring', term: filterMatch![2].trim() };
|
|
241
|
+
}
|
|
242
|
+
if (filterBy.includes('substringof')) {
|
|
243
|
+
const filterMatch = filterBy.match(/substringof\('(.*?)',\s([a-zA-Z\/]+)/);
|
|
244
|
+
const fieldName = filterMatch![2].trim();
|
|
245
|
+
(columnFilters as any)[fieldName] = { type: 'substring', term: filterMatch![1].trim() };
|
|
246
|
+
}
|
|
247
|
+
for (const operator of ['eq', 'ne', 'le', 'lt', 'gt', 'ge']) {
|
|
248
|
+
if (filterBy.includes(operator)) {
|
|
249
|
+
const re = new RegExp(`([a-zA-Z ]*) ${operator} \'(.*?)\'`);
|
|
250
|
+
const filterMatch = re.exec(filterBy);
|
|
251
|
+
if (Array.isArray(filterMatch)) {
|
|
252
|
+
const fieldName = filterMatch[1].trim();
|
|
253
|
+
(columnFilters as any)[fieldName] = { type: operator, term: filterMatch[2].trim() };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (filterBy.includes('startswith')) {
|
|
258
|
+
const filterMatch = filterBy.match(/startswith\(([a-zA-Z ]*),\s?'(.*?)'/);
|
|
259
|
+
const fieldName = filterMatch![1].trim();
|
|
260
|
+
(columnFilters as any)[fieldName] = { type: 'starts', term: filterMatch![2].trim() };
|
|
261
|
+
}
|
|
262
|
+
if (filterBy.includes('endswith')) {
|
|
263
|
+
const filterMatch = filterBy.match(/endswith\(([a-zA-Z ]*),\s?'(.*?)'/);
|
|
264
|
+
const fieldName = filterMatch![1].trim();
|
|
265
|
+
(columnFilters as any)[fieldName] = { type: 'ends', term: filterMatch![2].trim() };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// simulate a backend error when trying to sort on the "Company" field
|
|
269
|
+
if (filterBy.includes('company')) {
|
|
270
|
+
throw new Error('Server could not filter using the field "Company"');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// simulate a backend error when trying to sort on the "Company" field
|
|
276
|
+
if (orderBy.includes('company')) {
|
|
277
|
+
throw new Error('Server could not sort using the field "Company"');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.http.get(`${sampleDataRoot}/customers_100.json`).subscribe(response => {
|
|
281
|
+
let data = response as any[];
|
|
282
|
+
|
|
283
|
+
// Sort the data
|
|
284
|
+
if (orderBy?.length > 0) {
|
|
285
|
+
const orderByClauses = orderBy.split(',');
|
|
286
|
+
for (const orderByClause of orderByClauses) {
|
|
287
|
+
const orderByParts = orderByClause.split(' ');
|
|
288
|
+
const orderByField = orderByParts[0];
|
|
289
|
+
|
|
290
|
+
let selector = (obj: any): string => obj;
|
|
291
|
+
for (const orderByFieldPart of orderByField.split('/')) {
|
|
292
|
+
const prevSelector = selector;
|
|
293
|
+
selector = (obj: any) => {
|
|
294
|
+
return prevSelector(obj)[orderByFieldPart as any];
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const sort = orderByParts[1] ?? 'asc';
|
|
299
|
+
switch (sort.toLocaleLowerCase()) {
|
|
300
|
+
case 'asc':
|
|
301
|
+
data = data.sort((a, b) => selector(a).localeCompare(selector(b)));
|
|
302
|
+
break;
|
|
303
|
+
case 'desc':
|
|
304
|
+
data = data.sort((a, b) => selector(b).localeCompare(selector(a)));
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Read the result field from the JSON response.
|
|
311
|
+
const firstRow = skip;
|
|
312
|
+
let filteredData = data;
|
|
313
|
+
if (columnFilters) {
|
|
314
|
+
for (const columnId in columnFilters) {
|
|
315
|
+
if (columnFilters.hasOwnProperty(columnId)) {
|
|
316
|
+
filteredData = filteredData.filter(column => {
|
|
317
|
+
const filterType = (columnFilters as any)[columnId].type;
|
|
318
|
+
const searchTerm = (columnFilters as any)[columnId].term;
|
|
319
|
+
let colId = columnId;
|
|
320
|
+
if (columnId && columnId.indexOf(' ') !== -1) {
|
|
321
|
+
const splitIds = columnId.split(' ');
|
|
322
|
+
colId = splitIds[splitIds.length - 1];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let filterTerm;
|
|
326
|
+
let col = column;
|
|
327
|
+
for (const part of colId.split('/')) {
|
|
328
|
+
filterTerm = (col as any)[part];
|
|
329
|
+
col = filterTerm;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (filterTerm) {
|
|
333
|
+
switch (filterType) {
|
|
334
|
+
case 'eq': return filterTerm.toLowerCase() === searchTerm;
|
|
335
|
+
case 'ne': return filterTerm.toLowerCase() !== searchTerm;
|
|
336
|
+
case 'le': return filterTerm.toLowerCase() <= searchTerm;
|
|
337
|
+
case 'lt': return filterTerm.toLowerCase() < searchTerm;
|
|
338
|
+
case 'gt': return filterTerm.toLowerCase() > searchTerm;
|
|
339
|
+
case 'ge': return filterTerm.toLowerCase() >= searchTerm;
|
|
340
|
+
case 'ends': return filterTerm.toLowerCase().endsWith(searchTerm);
|
|
341
|
+
case 'starts': return filterTerm.toLowerCase().startsWith(searchTerm);
|
|
342
|
+
case 'substring': return filterTerm.toLowerCase().includes(searchTerm);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
countTotalItems = filteredData.length;
|
|
349
|
+
}
|
|
350
|
+
const updatedData = filteredData.slice(firstRow, firstRow + top!);
|
|
351
|
+
|
|
352
|
+
setTimeout(() => {
|
|
353
|
+
const backendResult: any = { query };
|
|
354
|
+
if (!this.isCountEnabled) {
|
|
355
|
+
backendResult['totalRecordCount'] = countTotalItems;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (this.odataVersion === 4) {
|
|
359
|
+
backendResult['value'] = updatedData;
|
|
360
|
+
if (this.isCountEnabled) {
|
|
361
|
+
backendResult['@odata.count'] = countTotalItems;
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
backendResult['d'] = { results: updatedData };
|
|
365
|
+
if (this.isCountEnabled) {
|
|
366
|
+
backendResult['d']['__count'] = countTotalItems;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// console.log('Backend Result', backendResult);
|
|
371
|
+
resolve(backendResult);
|
|
372
|
+
}, 100);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** Dispatched event of a Grid State Changed event */
|
|
378
|
+
gridStateChanged(gridStateChanges: GridStateChange) {
|
|
379
|
+
// console.log('Client sample, Grid State changed:: ', gridStateChanges);
|
|
380
|
+
console.log('Client sample, Grid State changed:: ', gridStateChanges.change);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
throwPageChangeError() {
|
|
384
|
+
this.isPageErrorTest = true;
|
|
385
|
+
this.angularGrid?.paginationService?.goToLastPage();
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// YOU CAN CHOOSE TO PREVENT EVENT FROM BUBBLING IN THE FOLLOWING 3x EVENTS
|
|
389
|
+
// note however that internally the cancelling the search is more of a rollback
|
|
390
|
+
handleOnBeforeSort(e: Event) {
|
|
391
|
+
// e.preventDefault();
|
|
392
|
+
// return false;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
handleOnBeforeSearchChange(e: Event) {
|
|
397
|
+
// e.preventDefault();
|
|
398
|
+
// return false;
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
handleOnBeforePaginationChange(e: Event) {
|
|
403
|
+
// e.preventDefault();
|
|
404
|
+
// return false;
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// THE FOLLOWING METHODS ARE ONLY FOR DEMO PURPOSES DO NOT USE THIS CODE
|
|
409
|
+
// ---
|
|
410
|
+
|
|
411
|
+
changeCountEnableFlag() {
|
|
412
|
+
this.isCountEnabled = !this.isCountEnabled;
|
|
413
|
+
this.resetOptions({ enableCount: this.isCountEnabled });
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
changeEnableSelectFlag() {
|
|
418
|
+
this.isSelectEnabled = !this.isSelectEnabled;
|
|
419
|
+
this.resetOptions({ enableSelect: this.isSelectEnabled });
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
changeEnableExpandFlag() {
|
|
424
|
+
this.isExpandEnabled = !this.isExpandEnabled;
|
|
425
|
+
this.resetOptions({ enableExpand: this.isExpandEnabled });
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
setOdataVersion(version: number) {
|
|
430
|
+
this.odataVersion = version;
|
|
431
|
+
this.resetOptions({ version: this.odataVersion });
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
private resetOptions(options: Partial<OdataOption>) {
|
|
436
|
+
const odataService = this.gridOptions.backendServiceApi!.service as GridOdataService;
|
|
437
|
+
odataService.updateOptions(options);
|
|
438
|
+
odataService.clearFilters();
|
|
439
|
+
this.angularGrid?.filterService.clearFilters();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<div class="container-fluid">
|
|
2
|
+
<h2>
|
|
3
|
+
{{title}}
|
|
4
|
+
<span class="float-end">
|
|
5
|
+
<a style="font-size: 18px"
|
|
6
|
+
target="_blank"
|
|
7
|
+
href="https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/examples/grid-range.component.ts">
|
|
8
|
+
<span class="fa fa-link"></span> code
|
|
9
|
+
</a>
|
|
10
|
+
</span>
|
|
11
|
+
</h2>
|
|
12
|
+
<div class="subtitle" [innerHTML]="subTitle"></div>
|
|
13
|
+
|
|
14
|
+
<br />
|
|
15
|
+
|
|
16
|
+
<span *ngIf="metrics" style="margin-right: 10px">
|
|
17
|
+
<b>Metrics:</b> {{metrics.startTime | date: 'yyyy-MM-dd hh:mm aaaaa\'m\''}} | {{metrics.itemCount}} of
|
|
18
|
+
{{metrics.totalItemCount}} items
|
|
19
|
+
</span>
|
|
20
|
+
|
|
21
|
+
<form class="row row-cols-lg-auto g-1 align-items-center">
|
|
22
|
+
<div class="col">
|
|
23
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="clear-filters" (click)="clearFilters()">
|
|
24
|
+
Clear Filters
|
|
25
|
+
</button>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="col">
|
|
28
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="clear-sorting"
|
|
29
|
+
(click)="angularGrid.sortService.clearSorting()">
|
|
30
|
+
Clear Sorting
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="col">
|
|
34
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="set-dynamic-filter" (click)="setFiltersDynamically()">
|
|
35
|
+
Set Filters Dynamically
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="col">
|
|
39
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="set-dynamic-sorting"
|
|
40
|
+
(click)="setSortingDynamically()">
|
|
41
|
+
Set Sorting Dynamically
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="col">
|
|
45
|
+
<label for="selectedFilter" style="margin-left: 10px">Predefined Filters</label>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="col">
|
|
48
|
+
<select name="selectedFilter" class="form-select" [(ngModel)]="selectedPredefinedFilter"
|
|
49
|
+
data-test="select-dynamic-filter" (ngModelChange)="usePredefinedFilter($event)">
|
|
50
|
+
<option [ngValue]="filter.value" *ngFor="let filter of filterList">{{filter.label}}</option>
|
|
51
|
+
</select>
|
|
52
|
+
</div>
|
|
53
|
+
</form>
|
|
54
|
+
|
|
55
|
+
<div class="row mt-2">
|
|
56
|
+
<div class="col">
|
|
57
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="language" (click)="switchLanguage()">
|
|
58
|
+
<i class="fa fa-language"></i>
|
|
59
|
+
Switch Language
|
|
60
|
+
</button>
|
|
61
|
+
<b>Locale:</b> <span style="font-style: italic" data-test="selected-locale">{{selectedLanguage + '.json'}}</span>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<angular-slickgrid gridId="grid25"
|
|
66
|
+
[columnDefinitions]="columnDefinitions"
|
|
67
|
+
[gridOptions]="gridOptions"
|
|
68
|
+
[dataset]="dataset"
|
|
69
|
+
(onAngularGridCreated)="angularGridReady($event.detail)"
|
|
70
|
+
(onGridStateChanged)="gridStateChanged($event.detail)"
|
|
71
|
+
(onBeforeGridDestroy)="saveCurrentGridState()"
|
|
72
|
+
(onRowCountChanged)="refreshMetrics($event.detail.eventData, $event.detail.args)">
|
|
73
|
+
</angular-slickgrid>
|
|
74
|
+
</div>
|