angular-slickgrid 4.1.2 → 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.
Files changed (242) hide show
  1. package/.browserslistrc +12 -0
  2. package/.codecov.yml +17 -0
  3. package/.editorconfig +18 -0
  4. package/.eslintrc.json +50 -0
  5. package/.github/CODE_OF_CONDUCT.md +76 -0
  6. package/.github/FUNDING.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/bug_report.yml +54 -0
  8. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  9. package/.github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  10. package/.github/renovate.json5 +26 -0
  11. package/.github/stale.yml +7 -0
  12. package/.github/workflows/main.yml +83 -0
  13. package/.vscode/extensions.json +9 -0
  14. package/.vscode/launch.json +72 -0
  15. package/.vscode/settings.json +7 -0
  16. package/.vscode/tasks.json +77 -0
  17. package/CHANGELOG.md +1172 -0
  18. package/LICENSE +20 -20
  19. package/README.md +9 -7
  20. package/angular.json +148 -0
  21. package/dist/LICENSE +20 -0
  22. package/dist/README.md +182 -0
  23. package/{angular-slickgrid.d.ts → dist/angular-slickgrid.d.ts} +0 -0
  24. package/{app → dist/app}/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +0 -0
  25. package/{app → dist/app}/modules/angular-slickgrid/constants.d.ts +0 -0
  26. package/{app → dist/app}/modules/angular-slickgrid/extensions/index.d.ts +0 -0
  27. package/{app → dist/app}/modules/angular-slickgrid/extensions/slickRowDetailView.d.ts +0 -0
  28. package/{app → dist/app}/modules/angular-slickgrid/global-grid-options.d.ts +0 -0
  29. package/{app → dist/app}/modules/angular-slickgrid/index.d.ts +0 -0
  30. package/{app → dist/app}/modules/angular-slickgrid/models/angularComponentOutput.interface.d.ts +0 -0
  31. package/{app → dist/app}/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +0 -0
  32. package/{app → dist/app}/modules/angular-slickgrid/models/externalTestingDependencies.interface.d.ts +0 -0
  33. package/{app → dist/app}/modules/angular-slickgrid/models/gridOption.interface.d.ts +0 -0
  34. package/{app → dist/app}/modules/angular-slickgrid/models/index.d.ts +0 -0
  35. package/{app → dist/app}/modules/angular-slickgrid/models/rowDetailView.interface.d.ts +0 -0
  36. package/{app → dist/app}/modules/angular-slickgrid/models/slickGrid.interface.d.ts +0 -0
  37. package/{app → dist/app}/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +0 -0
  38. package/{app → dist/app}/modules/angular-slickgrid/services/angularUtil.service.d.ts +0 -0
  39. package/{app → dist/app}/modules/angular-slickgrid/services/bsDropdown.service.d.ts +0 -0
  40. package/{app → dist/app}/modules/angular-slickgrid/services/container.service.d.ts +0 -0
  41. package/{app → dist/app}/modules/angular-slickgrid/services/index.d.ts +0 -0
  42. package/{app → dist/app}/modules/angular-slickgrid/services/translater.service.d.ts +0 -0
  43. package/{app → dist/app}/modules/angular-slickgrid/services/utilities.d.ts +0 -0
  44. package/{app → dist/app}/modules/angular-slickgrid/slickgrid-config.d.ts +0 -0
  45. package/{esm2020 → dist/esm2020}/angular-slickgrid.mjs +0 -0
  46. package/dist/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1171 -0
  47. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/constants.mjs +1 -1
  48. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/index.mjs +1 -1
  49. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +2 -2
  50. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/global-grid-options.mjs +1 -1
  51. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/index.mjs +1 -1
  52. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs +1 -1
  53. package/dist/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
  54. package/dist/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +2 -0
  55. package/dist/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +2 -0
  56. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/index.mjs +1 -1
  57. package/dist/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +2 -0
  58. package/dist/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +2 -0
  59. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +5 -5
  60. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/angularUtil.service.mjs +4 -4
  61. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +4 -4
  62. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/container.service.mjs +4 -4
  63. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/index.mjs +1 -1
  64. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/translater.service.mjs +4 -4
  65. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/utilities.mjs +1 -1
  66. package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/slickgrid-config.mjs +1 -1
  67. package/{esm2020 → dist/esm2020}/public_api.mjs +1 -1
  68. package/{fesm2015 → dist/fesm2015}/angular-slickgrid.mjs +25 -22
  69. package/dist/fesm2015/angular-slickgrid.mjs.map +1 -0
  70. package/{fesm2020 → dist/fesm2020}/angular-slickgrid.mjs +25 -22
  71. package/dist/fesm2020/angular-slickgrid.mjs.map +1 -0
  72. package/{i18n → dist/i18n}/en.json +89 -89
  73. package/{i18n → dist/i18n}/fr.json +90 -90
  74. package/dist/package.json +79 -0
  75. package/{public_api.d.ts → dist/public_api.d.ts} +0 -0
  76. package/global.d.ts +1 -0
  77. package/ngcc.config.js +13 -0
  78. package/package.json +124 -37
  79. package/screenshots/column-picker.png +0 -0
  80. package/screenshots/composite-editor.png +0 -0
  81. package/screenshots/draggable-grouping.png +0 -0
  82. package/screenshots/editors.png +0 -0
  83. package/screenshots/export-to-file.png +0 -0
  84. package/screenshots/filter_and_sort.png +0 -0
  85. package/screenshots/formatters.png +0 -0
  86. package/screenshots/frozen.png +0 -0
  87. package/screenshots/multipleSelectFilter.png +0 -0
  88. package/screenshots/pagination.png +0 -0
  89. package/screenshots/selectFilter.png +0 -0
  90. package/screenshots/singleFilter.png +0 -0
  91. package/src/app/app-routing.module.ts +83 -0
  92. package/src/app/app.component.html +160 -0
  93. package/src/app/app.component.scss +65 -0
  94. package/src/app/app.component.ts +10 -0
  95. package/src/app/app.module.ts +175 -0
  96. package/src/app/examples/custom-angularComponentEditor.ts +184 -0
  97. package/src/app/examples/custom-angularComponentFilter.ts +126 -0
  98. package/src/app/examples/custom-inputEditor.ts +124 -0
  99. package/src/app/examples/custom-inputFilter.ts +142 -0
  100. package/src/app/examples/custom-titleFormatter.component.ts +8 -0
  101. package/src/app/examples/editor-ng-select.component.ts +37 -0
  102. package/src/app/examples/filter-ng-select.component.ts +32 -0
  103. package/src/app/examples/grid-additem.component.html +48 -0
  104. package/src/app/examples/grid-additem.component.ts +272 -0
  105. package/src/app/examples/grid-angular.component.html +79 -0
  106. package/src/app/examples/grid-angular.component.scss +28 -0
  107. package/src/app/examples/grid-angular.component.ts +370 -0
  108. package/src/app/examples/grid-autoheight.component.html +52 -0
  109. package/src/app/examples/grid-autoheight.component.ts +147 -0
  110. package/src/app/examples/grid-basic.component.html +29 -0
  111. package/src/app/examples/grid-basic.component.ts +82 -0
  112. package/src/app/examples/grid-clientside.component.html +51 -0
  113. package/src/app/examples/grid-clientside.component.ts +293 -0
  114. package/src/app/examples/grid-colspan.component.html +39 -0
  115. package/src/app/examples/grid-colspan.component.scss +11 -0
  116. package/src/app/examples/grid-colspan.component.ts +155 -0
  117. package/src/app/examples/grid-composite-editor.component.html +79 -0
  118. package/src/app/examples/grid-composite-editor.component.scss +19 -0
  119. package/src/app/examples/grid-composite-editor.component.ts +948 -0
  120. package/src/app/examples/grid-contextmenu.component.html +62 -0
  121. package/src/app/examples/grid-contextmenu.component.scss +44 -0
  122. package/src/app/examples/grid-contextmenu.component.ts +473 -0
  123. package/src/app/examples/grid-custom-tooltip.component.html +25 -0
  124. package/src/app/examples/grid-custom-tooltip.component.scss +77 -0
  125. package/src/app/examples/grid-custom-tooltip.component.ts +483 -0
  126. package/src/app/examples/grid-draggrouping.component.html +93 -0
  127. package/src/app/examples/grid-draggrouping.component.ts +397 -0
  128. package/src/app/examples/grid-editor.component.html +88 -0
  129. package/src/app/examples/grid-editor.component.ts +699 -0
  130. package/src/app/examples/grid-formatter.component.html +26 -0
  131. package/src/app/examples/grid-formatter.component.ts +162 -0
  132. package/src/app/examples/grid-frozen.component.html +65 -0
  133. package/src/app/examples/grid-frozen.component.scss +11 -0
  134. package/src/app/examples/grid-frozen.component.ts +303 -0
  135. package/src/app/examples/grid-graphql-nopage.component.html +33 -0
  136. package/src/app/examples/grid-graphql-nopage.component.scss +9 -0
  137. package/src/app/examples/grid-graphql-nopage.component.ts +242 -0
  138. package/src/app/examples/grid-graphql.component.html +87 -0
  139. package/src/app/examples/grid-graphql.component.ts +304 -0
  140. package/src/app/examples/grid-grouping.component.html +80 -0
  141. package/src/app/examples/grid-grouping.component.ts +313 -0
  142. package/src/app/examples/grid-headerbutton.component.html +31 -0
  143. package/src/app/examples/grid-headerbutton.component.scss +10 -0
  144. package/src/app/examples/grid-headerbutton.component.ts +233 -0
  145. package/src/app/examples/grid-headermenu.component.html +31 -0
  146. package/src/app/examples/grid-headermenu.component.scss +25 -0
  147. package/src/app/examples/grid-headermenu.component.ts +159 -0
  148. package/src/app/examples/grid-localization.component.html +54 -0
  149. package/src/app/examples/grid-localization.component.ts +293 -0
  150. package/src/app/examples/grid-menu.component.html +37 -0
  151. package/src/app/examples/grid-menu.component.scss +28 -0
  152. package/src/app/examples/grid-menu.component.ts +229 -0
  153. package/src/app/examples/grid-odata.component.html +116 -0
  154. package/src/app/examples/grid-odata.component.ts +441 -0
  155. package/src/app/examples/grid-range.component.html +74 -0
  156. package/src/app/examples/grid-range.component.ts +291 -0
  157. package/src/app/examples/grid-remote.component.html +37 -0
  158. package/src/app/examples/grid-remote.component.ts +153 -0
  159. package/src/app/examples/grid-resize-by-content.component.html +62 -0
  160. package/src/app/examples/grid-resize-by-content.component.scss +19 -0
  161. package/src/app/examples/grid-resize-by-content.component.ts +780 -0
  162. package/src/app/examples/grid-rowdetail.component.html +35 -0
  163. package/src/app/examples/grid-rowdetail.component.ts +205 -0
  164. package/src/app/examples/grid-rowmove.component.html +49 -0
  165. package/src/app/examples/grid-rowmove.component.ts +234 -0
  166. package/src/app/examples/grid-rowselection.component.html +76 -0
  167. package/src/app/examples/grid-rowselection.component.ts +267 -0
  168. package/src/app/examples/grid-state.component.html +36 -0
  169. package/src/app/examples/grid-state.component.ts +259 -0
  170. package/src/app/examples/grid-tabs.component.html +35 -0
  171. package/src/app/examples/grid-tabs.component.ts +115 -0
  172. package/src/app/examples/grid-trading.component.html +58 -0
  173. package/src/app/examples/grid-trading.component.scss +49 -0
  174. package/src/app/examples/grid-trading.component.ts +319 -0
  175. package/src/app/examples/grid-tree-data-hierarchical.component.html +79 -0
  176. package/src/app/examples/grid-tree-data-hierarchical.component.scss +47 -0
  177. package/src/app/examples/grid-tree-data-hierarchical.component.ts +311 -0
  178. package/src/app/examples/grid-tree-data-parent-child.component.html +108 -0
  179. package/src/app/examples/grid-tree-data-parent-child.component.scss +10 -0
  180. package/src/app/examples/grid-tree-data-parent-child.component.ts +351 -0
  181. package/src/app/examples/home.component.html +41 -0
  182. package/src/app/examples/home.component.ts +9 -0
  183. package/src/app/examples/rowdetail-preload.component.ts +10 -0
  184. package/src/app/examples/rowdetail-view.component.html +36 -0
  185. package/src/app/examples/rowdetail-view.component.ts +54 -0
  186. package/src/app/examples/swt-common-grid-pagination.component.ts +156 -0
  187. package/src/app/examples/swt-common-grid-test.component.html +30 -0
  188. package/src/app/examples/swt-common-grid-test.component.ts +219 -0
  189. package/src/app/examples/swt-common-grid.component.ts +436 -0
  190. package/src/app/examples/swt-logger.service.ts +165 -0
  191. package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.html +4 -0
  192. package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts +1395 -0
  193. package/src/app/modules/angular-slickgrid/constants.ts +97 -0
  194. package/src/app/modules/angular-slickgrid/extensions/index.ts +1 -0
  195. package/src/app/modules/angular-slickgrid/extensions/slickRowDetailView.ts +375 -0
  196. package/src/app/modules/angular-slickgrid/global-grid-options.ts +245 -0
  197. package/src/app/modules/angular-slickgrid/index.ts +11 -0
  198. package/src/app/modules/angular-slickgrid/models/angularComponentOutput.interface.ts +6 -0
  199. package/src/app/modules/angular-slickgrid/models/angularGridInstance.interface.ts +68 -0
  200. package/src/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.ts +37 -0
  201. package/src/app/modules/angular-slickgrid/models/gridOption.interface.ts +12 -0
  202. package/src/app/modules/angular-slickgrid/models/index.ts +6 -0
  203. package/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts +33 -0
  204. package/src/app/modules/angular-slickgrid/models/slickGrid.interface.ts +7 -0
  205. package/src/app/modules/angular-slickgrid/modules/angular-slickgrid.module.ts +37 -0
  206. package/src/app/modules/angular-slickgrid/services/angularUtil.service.ts +48 -0
  207. package/src/app/modules/angular-slickgrid/services/bsDropdown.service.ts +142 -0
  208. package/src/app/modules/angular-slickgrid/services/container.service.ts +24 -0
  209. package/src/app/modules/angular-slickgrid/services/index.ts +5 -0
  210. package/src/app/modules/angular-slickgrid/services/translater.service.ts +38 -0
  211. package/src/app/modules/angular-slickgrid/services/utilities.ts +19 -0
  212. package/src/app/modules/angular-slickgrid/slickgrid-config.ts +10 -0
  213. package/src/app/slickgrid-custom-variables.scss +10 -0
  214. package/src/assets/.gitkeep +0 -0
  215. package/src/assets/data/collection_100_numbers.json +12 -0
  216. package/src/assets/data/collection_500_numbers.json +52 -0
  217. package/src/assets/data/countries.json +245 -0
  218. package/src/assets/data/country_names.json +245 -0
  219. package/src/assets/data/customers_100.json +102 -0
  220. package/src/assets/i18n/en.json +90 -0
  221. package/src/assets/i18n/fr.json +91 -0
  222. package/src/environments/environment.prod.ts +3 -0
  223. package/src/environments/environment.ts +8 -0
  224. package/src/favicon.ico +0 -0
  225. package/src/index.html +18 -0
  226. package/src/main.ts +13 -0
  227. package/src/polyfills.ts +52 -0
  228. package/src/public_api.ts +1 -0
  229. package/src/styles.scss +66 -0
  230. package/src/typings.d.ts +10 -0
  231. package/tsconfig.app.json +25 -0
  232. package/tsconfig.json +40 -0
  233. package/tsconfig.spec.json +23 -0
  234. package/docs/assets/lib/multiple-select/README.md +0 -17
  235. package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +0 -1168
  236. package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +0 -2
  237. package/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +0 -2
  238. package/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +0 -2
  239. package/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +0 -2
  240. package/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +0 -2
  241. package/fesm2015/angular-slickgrid.mjs.map +0 -1
  242. 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>