angular-slickgrid 8.14.1 → 9.0.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 (419) hide show
  1. package/.gitbook.yaml +5 -0
  2. package/CHANGELOG.md +1691 -0
  3. package/CONTRIBUTING.md +17 -0
  4. package/README.md +13 -50
  5. package/angular.json +133 -0
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +1620 -0
  9. package/coverage/coverage-final.json +9 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +176 -0
  12. package/coverage/library/components/angular-slickgrid.component.ts.html +5074 -0
  13. package/coverage/library/components/index.html +116 -0
  14. package/coverage/library/constants.ts.html +397 -0
  15. package/coverage/library/extensions/index.html +116 -0
  16. package/coverage/library/extensions/slickRowDetailView.ts.html +1261 -0
  17. package/coverage/library/index.html +116 -0
  18. package/coverage/library/modules/angular-slickgrid.module.ts.html +166 -0
  19. package/coverage/library/modules/index.html +116 -0
  20. package/coverage/library/services/angularUtil.service.ts.html +445 -0
  21. package/coverage/library/services/container.service.ts.html +163 -0
  22. package/coverage/library/services/index.html +161 -0
  23. package/coverage/library/services/translater.service.ts.html +199 -0
  24. package/coverage/library/services/utilities.ts.html +142 -0
  25. package/coverage/prettify.css +1 -0
  26. package/coverage/prettify.js +2 -0
  27. package/coverage/sort-arrow-sprite.png +0 -0
  28. package/coverage/sorter.js +196 -0
  29. package/dist/LICENSE +21 -0
  30. package/dist/README.md +142 -0
  31. package/{fesm2022 → dist/fesm2022}/angular-slickgrid.mjs +168 -194
  32. package/dist/fesm2022/angular-slickgrid.mjs.map +1 -0
  33. package/{i18n → dist/i18n}/en.json +2 -1
  34. package/{i18n → dist/i18n}/fr.json +2 -1
  35. package/{app/modules/angular-slickgrid → dist/library}/components/angular-slickgrid.component.d.ts +9 -9
  36. package/{app/modules/angular-slickgrid → dist/library}/extensions/slickRowDetailView.d.ts +4 -4
  37. package/{app/modules/angular-slickgrid → dist/library}/models/angularGridInstance.interface.d.ts +0 -2
  38. package/dist/library/models/index.d.ts +5 -0
  39. package/{app/modules/angular-slickgrid → dist/library}/models/rowDetailView.interface.d.ts +1 -1
  40. package/{app/modules/angular-slickgrid → dist/library}/modules/angular-slickgrid.module.d.ts +1 -1
  41. package/dist/public_api.d.ts +1 -0
  42. package/docs/README.md +5 -0
  43. package/docs/TOC.md +105 -0
  44. package/docs/backend-services/Custom-Backend-Service.md +50 -0
  45. package/docs/backend-services/GraphQL.md +276 -0
  46. package/docs/backend-services/OData.md +245 -0
  47. package/docs/backend-services/graphql/GraphQL-Filtering.md +156 -0
  48. package/docs/backend-services/graphql/GraphQL-JSON-Result.md +85 -0
  49. package/docs/backend-services/graphql/GraphQL-Pagination.md +77 -0
  50. package/docs/backend-services/graphql/GraphQL-Sorting.md +78 -0
  51. package/docs/column-functionalities/cell-menu.md +212 -0
  52. package/docs/column-functionalities/editors/autocomplete-editor.md +466 -0
  53. package/docs/column-functionalities/editors/date-editor-flatpickr.md +71 -0
  54. package/docs/column-functionalities/editors/date-editor-vanilla-calendar.md +91 -0
  55. package/docs/column-functionalities/editors/longtext-editor-textarea.md +80 -0
  56. package/docs/column-functionalities/editors/select-dropdown-editor.md +227 -0
  57. package/docs/column-functionalities/editors.md +604 -0
  58. package/docs/column-functionalities/filters/autocomplete-filter.md +183 -0
  59. package/docs/column-functionalities/filters/compound-filters.md +234 -0
  60. package/docs/column-functionalities/filters/custom-filter.md +117 -0
  61. package/docs/column-functionalities/filters/filter-intro.md +81 -0
  62. package/docs/column-functionalities/filters/input-filter.md +260 -0
  63. package/docs/column-functionalities/filters/range-filters.md +188 -0
  64. package/docs/column-functionalities/filters/select-filter.md +695 -0
  65. package/docs/column-functionalities/filters/single-search-filter.md +77 -0
  66. package/docs/column-functionalities/filters/styling-filled-filters.md +45 -0
  67. package/docs/column-functionalities/formatters.md +325 -0
  68. package/docs/column-functionalities/sorting.md +200 -0
  69. package/docs/developer-guides/csp-compliance.md +64 -0
  70. package/docs/events/Available-Events.md +223 -0
  71. package/docs/events/Grid-&-DataView-Events.md +211 -0
  72. package/docs/getting-started/quick-start.md +230 -0
  73. package/docs/getting-started/troubleshooting.md +80 -0
  74. package/docs/grid-functionalities/Column-Picker.md +22 -0
  75. package/docs/grid-functionalities/Composite-Editor-Modal.md +627 -0
  76. package/docs/grid-functionalities/Context-Menu.md +226 -0
  77. package/docs/grid-functionalities/Custom-Footer.md +80 -0
  78. package/docs/grid-functionalities/Custom-Tooltip-(plugin).md +258 -0
  79. package/docs/grid-functionalities/Export-to-Excel.md +457 -0
  80. package/docs/grid-functionalities/Export-to-Text-File.md +165 -0
  81. package/docs/grid-functionalities/FAQ.md +53 -0
  82. package/docs/grid-functionalities/Global-Options.md +29 -0
  83. package/docs/grid-functionalities/Grid-Auto-Resize.md +218 -0
  84. package/docs/grid-functionalities/Grid-Menu.md +134 -0
  85. package/docs/grid-functionalities/Grid-State-&-Preset.md +245 -0
  86. package/docs/grid-functionalities/Header-Menu-&-Header-Buttons.md +125 -0
  87. package/docs/grid-functionalities/Resize-by-Cell-Content.md +138 -0
  88. package/docs/grid-functionalities/Row-Selection.md +247 -0
  89. package/docs/grid-functionalities/Row-based-edit.md +71 -0
  90. package/docs/grid-functionalities/add-update-highlight.md +258 -0
  91. package/docs/grid-functionalities/column-row-spanning.md +74 -0
  92. package/docs/grid-functionalities/dynamic-item-metadata.md +124 -0
  93. package/docs/grid-functionalities/excel-copy-buffer.md +145 -0
  94. package/docs/grid-functionalities/frozen-columns-rows.md +164 -0
  95. package/docs/grid-functionalities/grouping-and-aggregators.md +269 -0
  96. package/docs/grid-functionalities/header-footer-slots.md +22 -0
  97. package/docs/grid-functionalities/infinite-scroll.md +150 -0
  98. package/docs/grid-functionalities/providing-grid-data.md +61 -0
  99. package/docs/grid-functionalities/row-detail.md +530 -0
  100. package/docs/grid-functionalities/tree-data-grid.md +391 -0
  101. package/docs/localization/Localization---Component-Sample.md +87 -0
  102. package/docs/localization/Localization-with-Custom-Locales.md +66 -0
  103. package/docs/localization/Localization-with-ngx-translate.md +148 -0
  104. package/docs/migrations/migration-to-2.x.md +304 -0
  105. package/docs/migrations/migration-to-3.x.md +295 -0
  106. package/docs/migrations/migration-to-4.x.md +83 -0
  107. package/docs/migrations/migration-to-5.x.md +160 -0
  108. package/docs/migrations/migration-to-6.x.md +128 -0
  109. package/docs/migrations/migration-to-7.x.md +294 -0
  110. package/docs/migrations/migration-to-8.x.md +316 -0
  111. package/docs/migrations/migration-to-9.x.md +219 -0
  112. package/docs/slick-grid-dataview-objects/slickgrid-dataview-objects.md +79 -0
  113. package/docs/styling/dark-mode.md +100 -0
  114. package/docs/styling/styling.md +250 -0
  115. package/docs/testing/testing-patterns.md +73 -0
  116. package/eslint.config.mjs +60 -0
  117. package/ng-package.json +10 -0
  118. package/package.json +24 -48
  119. package/src/assets/angular-logo.png +0 -0
  120. package/src/assets/angular-logo2.png +0 -0
  121. package/src/assets/data/collection_100_numbers.json +12 -0
  122. package/src/assets/data/collection_500_numbers.json +52 -0
  123. package/src/assets/data/countries.json +245 -0
  124. package/src/assets/data/country_names.json +245 -0
  125. package/src/assets/data/customers_100.json +102 -0
  126. package/src/assets/data/users.csv +5 -0
  127. package/src/assets/i18n/en.json +102 -0
  128. package/src/assets/i18n/fr.json +103 -0
  129. package/src/demos/app-routing.module.ts +108 -0
  130. package/src/demos/app.component.html +187 -0
  131. package/src/demos/app.component.scss +79 -0
  132. package/src/demos/app.component.ts +11 -0
  133. package/src/demos/app.module.ts +196 -0
  134. package/src/demos/environments/environment.dev.ts +3 -0
  135. package/src/demos/environments/environment.prod.ts +3 -0
  136. package/src/demos/environments/environment.ts +8 -0
  137. package/src/demos/examples/custom-angularComponentEditor.ts +187 -0
  138. package/src/demos/examples/custom-angularComponentFilter.ts +123 -0
  139. package/src/demos/examples/custom-buttonFormatter.component.ts +13 -0
  140. package/src/demos/examples/custom-inputEditor.ts +132 -0
  141. package/src/demos/examples/custom-inputFilter.ts +134 -0
  142. package/src/demos/examples/custom-titleFormatter.component.ts +9 -0
  143. package/src/demos/examples/data/collection_100_numbers.json +12 -0
  144. package/src/demos/examples/data/collection_500_numbers.json +52 -0
  145. package/src/demos/examples/data/countries.json +245 -0
  146. package/src/demos/examples/data/country_names.json +245 -0
  147. package/src/demos/examples/data/customers_100.json +102 -0
  148. package/src/demos/examples/data/users.csv +5 -0
  149. package/src/demos/examples/editor-ng-select.component.ts +38 -0
  150. package/src/demos/examples/example01.component.html +48 -0
  151. package/src/demos/examples/example01.component.ts +109 -0
  152. package/src/demos/examples/example02.component.html +45 -0
  153. package/src/demos/examples/example02.component.ts +218 -0
  154. package/src/demos/examples/example03.component.html +118 -0
  155. package/src/demos/examples/example03.component.ts +694 -0
  156. package/src/demos/examples/example04.component.html +87 -0
  157. package/src/demos/examples/example04.component.ts +326 -0
  158. package/src/demos/examples/example05.component.html +151 -0
  159. package/src/demos/examples/example05.component.ts +474 -0
  160. package/src/demos/examples/example06.component.html +163 -0
  161. package/src/demos/examples/example06.component.ts +446 -0
  162. package/src/demos/examples/example07.component.html +56 -0
  163. package/src/demos/examples/example07.component.scss +10 -0
  164. package/src/demos/examples/example07.component.ts +216 -0
  165. package/src/demos/examples/example08.component.html +51 -0
  166. package/src/demos/examples/example08.component.scss +23 -0
  167. package/src/demos/examples/example08.component.ts +195 -0
  168. package/src/demos/examples/example09.component.html +55 -0
  169. package/src/demos/examples/example09.component.scss +22 -0
  170. package/src/demos/examples/example09.component.ts +302 -0
  171. package/src/demos/examples/example10.component.html +103 -0
  172. package/src/demos/examples/example10.component.ts +309 -0
  173. package/src/demos/examples/example11.component.html +91 -0
  174. package/src/demos/examples/example11.component.ts +276 -0
  175. package/src/demos/examples/example12.component.html +98 -0
  176. package/src/demos/examples/example12.component.ts +317 -0
  177. package/src/demos/examples/example13.component.html +96 -0
  178. package/src/demos/examples/example13.component.ts +370 -0
  179. package/src/demos/examples/example14.component.html +50 -0
  180. package/src/demos/examples/example14.component.scss +11 -0
  181. package/src/demos/examples/example14.component.ts +156 -0
  182. package/src/demos/examples/example15.component.html +56 -0
  183. package/src/demos/examples/example15.component.ts +304 -0
  184. package/src/demos/examples/example16.component.html +77 -0
  185. package/src/demos/examples/example16.component.ts +277 -0
  186. package/src/demos/examples/example17.component.html +50 -0
  187. package/src/demos/examples/example17.component.ts +109 -0
  188. package/src/demos/examples/example18.component.html +132 -0
  189. package/src/demos/examples/example18.component.ts +445 -0
  190. package/src/demos/examples/example19-rowdetail.component.html +40 -0
  191. package/src/demos/examples/example19-rowdetail.component.ts +54 -0
  192. package/src/demos/examples/example19.component.html +79 -0
  193. package/src/demos/examples/example19.component.ts +316 -0
  194. package/src/demos/examples/example20.component.html +76 -0
  195. package/src/demos/examples/example20.component.scss +11 -0
  196. package/src/demos/examples/example20.component.ts +341 -0
  197. package/src/demos/examples/example21.component.html +86 -0
  198. package/src/demos/examples/example21.component.scss +16 -0
  199. package/src/demos/examples/example21.component.ts +140 -0
  200. package/src/demos/examples/example22.component.html +41 -0
  201. package/src/demos/examples/example22.component.ts +117 -0
  202. package/src/demos/examples/example23.component.html +111 -0
  203. package/src/demos/examples/example23.component.ts +323 -0
  204. package/src/demos/examples/example24.component.html +120 -0
  205. package/src/demos/examples/example24.component.scss +62 -0
  206. package/src/demos/examples/example24.component.ts +641 -0
  207. package/src/demos/examples/example25.component.html +60 -0
  208. package/src/demos/examples/example25.component.scss +8 -0
  209. package/src/demos/examples/example25.component.ts +255 -0
  210. package/src/demos/examples/example26.component.html +98 -0
  211. package/src/demos/examples/example26.component.scss +42 -0
  212. package/src/demos/examples/example26.component.ts +383 -0
  213. package/src/demos/examples/example27.component.html +138 -0
  214. package/src/demos/examples/example27.component.scss +10 -0
  215. package/src/demos/examples/example27.component.ts +369 -0
  216. package/src/demos/examples/example28.component.html +143 -0
  217. package/src/demos/examples/example28.component.scss +54 -0
  218. package/src/demos/examples/example28.component.ts +453 -0
  219. package/src/demos/examples/example29.component.html +30 -0
  220. package/src/demos/examples/example29.component.ts +70 -0
  221. package/src/demos/examples/example30.component.html +116 -0
  222. package/src/demos/examples/example30.component.scss +20 -0
  223. package/src/demos/examples/example30.component.ts +1070 -0
  224. package/src/demos/examples/example32.component.html +77 -0
  225. package/src/demos/examples/example32.component.scss +8 -0
  226. package/src/demos/examples/example32.component.ts +905 -0
  227. package/src/demos/examples/example33.component.html +50 -0
  228. package/src/demos/examples/example33.component.scss +46 -0
  229. package/src/demos/examples/example33.component.ts +571 -0
  230. package/src/demos/examples/example34.component.html +82 -0
  231. package/src/demos/examples/example34.component.scss +77 -0
  232. package/src/demos/examples/example34.component.ts +434 -0
  233. package/src/demos/examples/example35.component.html +77 -0
  234. package/src/demos/examples/example35.component.scss +18 -0
  235. package/src/demos/examples/example35.component.ts +264 -0
  236. package/src/demos/examples/example36.component.html +56 -0
  237. package/src/demos/examples/example36.component.scss +26 -0
  238. package/src/demos/examples/example36.component.ts +504 -0
  239. package/src/demos/examples/example37.component.html +30 -0
  240. package/src/demos/examples/example37.component.ts +123 -0
  241. package/src/demos/examples/example38.component.html +104 -0
  242. package/src/demos/examples/example38.component.scss +8 -0
  243. package/src/demos/examples/example38.component.ts +420 -0
  244. package/src/demos/examples/example39.component.html +112 -0
  245. package/src/demos/examples/example39.component.scss +8 -0
  246. package/src/demos/examples/example39.component.ts +371 -0
  247. package/src/demos/examples/example40.component.html +76 -0
  248. package/src/demos/examples/example40.component.ts +226 -0
  249. package/src/demos/examples/example41.component.html +50 -0
  250. package/src/demos/examples/example41.component.scss +42 -0
  251. package/src/demos/examples/example41.component.ts +229 -0
  252. package/src/demos/examples/example42.component.html +47 -0
  253. package/src/demos/examples/example42.component.ts +203 -0
  254. package/src/demos/examples/example43.component.html +94 -0
  255. package/src/demos/examples/example43.component.scss +30 -0
  256. package/src/demos/examples/example43.component.ts +449 -0
  257. package/src/demos/examples/example44.component.html +78 -0
  258. package/src/demos/examples/example44.component.scss +50 -0
  259. package/src/demos/examples/example44.component.ts +375 -0
  260. package/src/demos/examples/example45-detail.component.html +15 -0
  261. package/src/demos/examples/example45-detail.component.ts +97 -0
  262. package/src/demos/examples/example45.component.html +110 -0
  263. package/src/demos/examples/example45.component.scss +50 -0
  264. package/src/demos/examples/example45.component.ts +243 -0
  265. package/src/demos/examples/filter-ng-select.component.ts +33 -0
  266. package/src/demos/examples/grid-custom-pager.component.html +60 -0
  267. package/src/demos/examples/grid-custom-pager.component.scss +57 -0
  268. package/src/demos/examples/grid-custom-pager.component.ts +107 -0
  269. package/src/demos/examples/grid-remote.component.html +44 -0
  270. package/src/demos/examples/grid-remote.component.ts +164 -0
  271. package/src/demos/examples/home.component.html +39 -0
  272. package/src/demos/examples/home.component.ts +10 -0
  273. package/src/demos/examples/jsonp.ts +89 -0
  274. package/src/demos/examples/rowdetail-preload.component.ts +10 -0
  275. package/src/demos/examples/swt-common-grid-pagination.component.ts +160 -0
  276. package/src/demos/examples/swt-common-grid-test.component.html +37 -0
  277. package/src/demos/examples/swt-common-grid-test.component.ts +214 -0
  278. package/src/demos/examples/swt-common-grid.component.ts +436 -0
  279. package/src/demos/examples/swt-logger.service.ts +173 -0
  280. package/src/demos/examples/utilities.ts +9 -0
  281. package/src/favicon.ico +0 -0
  282. package/src/index.html +17 -0
  283. package/src/library/components/__tests__/angular-slickgrid.component.spec.ts +2638 -0
  284. package/src/library/components/angular-slickgrid.component.html +5 -0
  285. package/src/library/components/angular-slickgrid.component.ts +1662 -0
  286. package/src/library/constants.ts +105 -0
  287. package/src/library/extensions/__tests__/slickRowDetailView.spec.ts +751 -0
  288. package/src/library/extensions/index.ts +1 -0
  289. package/src/library/extensions/slickRowDetailView.ts +395 -0
  290. package/src/library/global-grid-options.ts +273 -0
  291. package/src/library/index.ts +11 -0
  292. package/src/library/models/angularComponentOutput.interface.ts +6 -0
  293. package/src/library/models/angularGridInstance.interface.ts +76 -0
  294. package/src/library/models/externalTestingDependencies.interface.ts +37 -0
  295. package/src/library/models/gridOption.interface.ts +15 -0
  296. package/src/library/models/index.ts +5 -0
  297. package/src/library/models/rowDetailView.interface.ts +16 -0
  298. package/src/library/modules/angular-slickgrid.module.spec.ts +25 -0
  299. package/src/library/modules/angular-slickgrid.module.ts +27 -0
  300. package/src/library/services/__tests__/angularUtilService.spec.ts +156 -0
  301. package/src/library/services/__tests__/container.service.spec.ts +25 -0
  302. package/src/library/services/__tests__/translater.service.spec.ts +43 -0
  303. package/src/library/services/__tests__/utilities.spec.ts +22 -0
  304. package/src/library/services/angularUtil.service.ts +120 -0
  305. package/src/library/services/container.service.ts +26 -0
  306. package/src/library/services/index.ts +4 -0
  307. package/src/library/services/translater.service.ts +38 -0
  308. package/src/library/services/utilities.ts +19 -0
  309. package/src/library/slickgrid-config.ts +10 -0
  310. package/src/main.ts +13 -0
  311. package/src/public_api.ts +1 -0
  312. package/src/styles.scss +178 -0
  313. package/test/cypress/e2e/example01.cy.ts +367 -0
  314. package/test/cypress/e2e/example02.cy.ts +60 -0
  315. package/test/cypress/e2e/example03.cy.ts +268 -0
  316. package/test/cypress/e2e/example04.cy.ts +254 -0
  317. package/test/cypress/e2e/example05.cy.ts +804 -0
  318. package/test/cypress/e2e/example06.cy.ts +890 -0
  319. package/test/cypress/e2e/example07.cy.ts +384 -0
  320. package/test/cypress/e2e/example08.cy.ts +190 -0
  321. package/test/cypress/e2e/example09.cy.ts +392 -0
  322. package/test/cypress/e2e/example10.cy.ts +650 -0
  323. package/test/cypress/e2e/example11.cy.ts +86 -0
  324. package/test/cypress/e2e/example12.cy.ts +269 -0
  325. package/test/cypress/e2e/example13.cy.ts +246 -0
  326. package/test/cypress/e2e/example14.cy.ts +122 -0
  327. package/test/cypress/e2e/example15.cy.ts +598 -0
  328. package/test/cypress/e2e/example16.cy.ts +427 -0
  329. package/test/cypress/e2e/example17.cy.ts +83 -0
  330. package/test/cypress/e2e/example18.cy.ts +431 -0
  331. package/test/cypress/e2e/example19.cy.ts +263 -0
  332. package/test/cypress/e2e/example20.cy.ts +264 -0
  333. package/test/cypress/e2e/example21.cy.ts +77 -0
  334. package/test/cypress/e2e/example22.cy.ts +94 -0
  335. package/test/cypress/e2e/example23.cy.ts +259 -0
  336. package/test/cypress/e2e/example24.cy.ts +707 -0
  337. package/test/cypress/e2e/example25.cy.ts +193 -0
  338. package/test/cypress/e2e/example26.cy.ts +111 -0
  339. package/test/cypress/e2e/example27.cy.ts +261 -0
  340. package/test/cypress/e2e/example28.cy.ts +740 -0
  341. package/test/cypress/e2e/example29.cy.ts +30 -0
  342. package/test/cypress/e2e/example30.cy.ts +757 -0
  343. package/test/cypress/e2e/example31.cy.ts +69 -0
  344. package/test/cypress/e2e/example32.cy.ts +272 -0
  345. package/test/cypress/e2e/example33.cy.ts +278 -0
  346. package/test/cypress/e2e/example34.cy.ts +84 -0
  347. package/test/cypress/e2e/example35.cy.ts +178 -0
  348. package/test/cypress/e2e/example36.cy.ts +219 -0
  349. package/test/cypress/e2e/example37.cy.ts +52 -0
  350. package/test/cypress/e2e/example38.cy.ts +160 -0
  351. package/test/cypress/e2e/example39.cy.ts +150 -0
  352. package/test/cypress/e2e/example40.cy.ts +126 -0
  353. package/test/cypress/e2e/example41.cy.ts +90 -0
  354. package/test/cypress/e2e/example42.cy.ts +82 -0
  355. package/test/cypress/e2e/example43.cy.ts +482 -0
  356. package/test/cypress/e2e/example44.cy.ts +458 -0
  357. package/test/cypress/e2e/example45.cy.ts +455 -0
  358. package/test/cypress/e2e/home.cy.ts +7 -0
  359. package/test/cypress/fixtures/example.json +5 -0
  360. package/test/cypress/plugins/index.ts +17 -0
  361. package/test/cypress/plugins/utilities.ts +28 -0
  362. package/test/cypress/support/commands.ts +88 -0
  363. package/test/cypress/support/common.ts +47 -0
  364. package/test/cypress/support/drag.ts +101 -0
  365. package/test/cypress/support/index.ts +20 -0
  366. package/test/cypress/tsconfig.json +9 -0
  367. package/test/cypress.config.ts +34 -0
  368. package/test/mockSlickEvent.ts +77 -0
  369. package/test/rxjsResourceStub.ts +69 -0
  370. package/test/test-setup.ts +6 -0
  371. package/test/translateServiceStub.ts +230 -0
  372. package/test/translaterServiceStub.ts +239 -0
  373. package/test/tsconfig.json +17 -0
  374. package/test/vitest-global-mocks.ts +41 -0
  375. package/test/vitest-global-setup.ts +3 -0
  376. package/test/vitest-pretest.ts +5 -0
  377. package/tsconfig.app.json +14 -0
  378. package/tsconfig.json +31 -0
  379. package/tsconfig.spec.json +11 -0
  380. package/types/sortablejs.d.ts +4 -0
  381. package/vite.config.mts +51 -0
  382. package/app/modules/angular-slickgrid/models/index.d.ts +0 -5
  383. package/esm2022/angular-slickgrid.mjs +0 -5
  384. package/esm2022/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +0 -1407
  385. package/esm2022/app/modules/angular-slickgrid/constants.mjs +0 -96
  386. package/esm2022/app/modules/angular-slickgrid/extensions/index.mjs +0 -2
  387. package/esm2022/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +0 -304
  388. package/esm2022/app/modules/angular-slickgrid/global-grid-options.mjs +0 -263
  389. package/esm2022/app/modules/angular-slickgrid/index.mjs +0 -8
  390. package/esm2022/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs +0 -2
  391. package/esm2022/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +0 -2
  392. package/esm2022/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +0 -2
  393. package/esm2022/app/modules/angular-slickgrid/models/gridOption.interface.mjs +0 -2
  394. package/esm2022/app/modules/angular-slickgrid/models/index.mjs +0 -6
  395. package/esm2022/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +0 -2
  396. package/esm2022/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +0 -32
  397. package/esm2022/app/modules/angular-slickgrid/services/angularUtil.service.mjs +0 -88
  398. package/esm2022/app/modules/angular-slickgrid/services/container.service.mjs +0 -27
  399. package/esm2022/app/modules/angular-slickgrid/services/index.mjs +0 -5
  400. package/esm2022/app/modules/angular-slickgrid/services/translater.service.mjs +0 -45
  401. package/esm2022/app/modules/angular-slickgrid/services/utilities.mjs +0 -19
  402. package/esm2022/app/modules/angular-slickgrid/slickgrid-config.mjs +0 -8
  403. package/esm2022/public_api.mjs +0 -2
  404. package/fesm2022/angular-slickgrid.mjs.map +0 -1
  405. package/public_api.d.ts +0 -1
  406. /package/{index.d.ts → dist/index.d.ts} +0 -0
  407. /package/{app/modules/angular-slickgrid → dist/library}/constants.d.ts +0 -0
  408. /package/{app/modules/angular-slickgrid → dist/library}/extensions/index.d.ts +0 -0
  409. /package/{app/modules/angular-slickgrid → dist/library}/global-grid-options.d.ts +0 -0
  410. /package/{app/modules/angular-slickgrid → dist/library}/index.d.ts +0 -0
  411. /package/{app/modules/angular-slickgrid → dist/library}/models/angularComponentOutput.interface.d.ts +0 -0
  412. /package/{app/modules/angular-slickgrid → dist/library}/models/externalTestingDependencies.interface.d.ts +0 -0
  413. /package/{app/modules/angular-slickgrid → dist/library}/models/gridOption.interface.d.ts +0 -0
  414. /package/{app/modules/angular-slickgrid → dist/library}/services/angularUtil.service.d.ts +0 -0
  415. /package/{app/modules/angular-slickgrid → dist/library}/services/container.service.d.ts +0 -0
  416. /package/{app/modules/angular-slickgrid → dist/library}/services/index.d.ts +0 -0
  417. /package/{app/modules/angular-slickgrid → dist/library}/services/translater.service.d.ts +0 -0
  418. /package/{app/modules/angular-slickgrid → dist/library}/services/utilities.d.ts +0 -0
  419. /package/{app/modules/angular-slickgrid → dist/library}/slickgrid-config.d.ts +0 -0
@@ -0,0 +1,504 @@
1
+ import { Component, OnInit, ViewEncapsulation } from '@angular/core';
2
+ import {
3
+ Aggregator,
4
+ Aggregators,
5
+ AngularGridInstance,
6
+ Column,
7
+ Editors,
8
+ ExcelCellValueParserArgs,
9
+ ExcelGroupValueParserArgs,
10
+ Formatter,
11
+ Formatters,
12
+ GridOption,
13
+ GroupTotalFormatters,
14
+ Grouping,
15
+ SlickGrid,
16
+ SlickGroupTotals,
17
+ } from '../../library';
18
+ import { ExcelExportService } from '@slickgrid-universal/excel-export';
19
+
20
+ interface GroceryItem {
21
+ id: number;
22
+ name: string;
23
+ qty: number;
24
+ price: number;
25
+ taxable: boolean;
26
+ subTotal: number;
27
+ taxes: number;
28
+ total: number;
29
+ }
30
+
31
+ /** Check if the current item (cell) is editable or not */
32
+ function checkItemIsEditable(_dataContext: GroceryItem, columnDef: Column, grid: SlickGrid) {
33
+ const gridOptions = grid.getOptions();
34
+ const hasEditor = columnDef.editor;
35
+ const isGridEditable = gridOptions.editable;
36
+ const isEditable = isGridEditable && hasEditor;
37
+
38
+ return isEditable;
39
+ }
40
+
41
+ const customEditableInputFormatter: Formatter = (_row, _cell, value, columnDef, dataContext: GroceryItem, grid) => {
42
+ const isEditableItem = checkItemIsEditable(dataContext, columnDef, grid);
43
+ value = value === null || value === undefined ? '' : value;
44
+ const divElm = document.createElement('div');
45
+ divElm.className = 'editing-field';
46
+ if (value instanceof HTMLElement) {
47
+ divElm.appendChild(value);
48
+ } else {
49
+ divElm.textContent = value;
50
+ }
51
+ return isEditableItem ? divElm : value;
52
+ };
53
+
54
+ /** Create a Custom Aggregator in order to calculate all Totals by accessing other fields of the item dataContext */
55
+ export class CustomSumAggregator implements Aggregator {
56
+ private _sum = 0;
57
+ private _type = 'sum' as const;
58
+
59
+ constructor(
60
+ public readonly field: number | string,
61
+ public taxRate: number
62
+ ) {}
63
+
64
+ get type(): string {
65
+ return this._type;
66
+ }
67
+
68
+ init() {
69
+ this._sum = 0;
70
+ }
71
+
72
+ accumulate(item: GroceryItem) {
73
+ if (this.field === 'taxes' && item['taxable']) {
74
+ this._sum += item['price'] * item['qty'] * (this.taxRate / 100);
75
+ }
76
+ if (this.field === 'subTotal') {
77
+ this._sum += item['price'] * item['qty'];
78
+ }
79
+ if (this.field === 'total') {
80
+ let taxes = 0;
81
+ if (item['taxable']) {
82
+ taxes = item['price'] * item['qty'] * (this.taxRate / 100);
83
+ }
84
+ this._sum += item['price'] * item['qty'] + taxes;
85
+ }
86
+ }
87
+
88
+ storeResult(groupTotals: any) {
89
+ if (!groupTotals || groupTotals[this._type] === undefined) {
90
+ groupTotals[this._type] = {};
91
+ }
92
+ groupTotals[this._type][this.field] = this._sum;
93
+ }
94
+ }
95
+
96
+ @Component({
97
+ templateUrl: './example36.component.html',
98
+ styleUrls: ['./example36.component.scss'],
99
+ encapsulation: ViewEncapsulation.None,
100
+ standalone: false,
101
+ })
102
+ export class Example36Component implements OnInit {
103
+ columnDefinitions: Column<GroceryItem>[] = [];
104
+ gridOptions!: GridOption;
105
+ dataset: GroceryItem[] = [];
106
+ angularGrid!: AngularGridInstance;
107
+ excelExportService: ExcelExportService;
108
+ isDataGrouped = false;
109
+ taxRate = 7.5;
110
+
111
+ constructor() {
112
+ this.excelExportService = new ExcelExportService();
113
+ }
114
+
115
+ angularGridReady(angularGrid: AngularGridInstance) {
116
+ this.angularGrid = angularGrid;
117
+ }
118
+
119
+ ngOnInit() {
120
+ this.prepareGrid();
121
+
122
+ // mock a dataset
123
+ this.dataset = this.getData();
124
+ }
125
+
126
+ prepareGrid() {
127
+ this.columnDefinitions = [
128
+ {
129
+ id: 'sel',
130
+ name: '#',
131
+ field: 'id',
132
+ headerCssClass: 'header-centered',
133
+ cssClass: 'cell-unselectable',
134
+ excludeFromExport: true,
135
+ maxWidth: 30,
136
+ },
137
+ {
138
+ id: 'name',
139
+ name: 'Name',
140
+ field: 'name',
141
+ sortable: true,
142
+ width: 140,
143
+ filterable: true,
144
+ excelExportOptions: { width: 18 },
145
+ },
146
+ {
147
+ id: 'price',
148
+ name: 'Price',
149
+ field: 'price',
150
+ type: 'number',
151
+ editor: { model: Editors.float, decimal: 2 },
152
+ sortable: true,
153
+ width: 70,
154
+ filterable: true,
155
+ formatter: Formatters.dollar,
156
+ groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollarBold,
157
+ groupTotalsExcelExportOptions: {
158
+ style: {
159
+ font: { bold: true, size: 11.5 },
160
+ format: '$0.00', // currency format
161
+ border: { top: { color: 'FF747474', style: 'thick' } },
162
+ },
163
+ valueParserCallback: this.excelGroupCellParser.bind(this),
164
+ },
165
+ },
166
+ {
167
+ id: 'qty',
168
+ name: 'Quantity',
169
+ field: 'qty',
170
+ type: 'number',
171
+ groupTotalsFormatter: GroupTotalFormatters.sumTotalsBold,
172
+ groupTotalsExcelExportOptions: {
173
+ style: {
174
+ font: { bold: true, size: 11.5 },
175
+ border: { top: { color: 'FF747474', style: 'thick' } },
176
+ },
177
+ valueParserCallback: this.excelGroupCellParser.bind(this),
178
+ },
179
+ params: { minDecimal: 0, maxDecimal: 0 },
180
+ editor: { model: Editors.integer },
181
+ sortable: true,
182
+ width: 60,
183
+ filterable: true,
184
+ },
185
+ {
186
+ id: 'subTotal',
187
+ name: 'Sub-Total',
188
+ field: 'subTotal',
189
+ cssClass: 'text-sub-total',
190
+ type: 'number',
191
+ sortable: true,
192
+ width: 70,
193
+ filterable: true,
194
+ exportWithFormatter: false,
195
+ formatter: Formatters.multiple,
196
+ groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollarBold,
197
+ params: {
198
+ formatters: [
199
+ (_row, _cell, _value, _coldef, dataContext) => dataContext.price * dataContext.qty,
200
+ Formatters.dollar,
201
+ ] as Formatter[],
202
+ },
203
+ excelExportOptions: {
204
+ style: {
205
+ font: { outline: true, italic: true, color: 'FF215073' },
206
+ format: '$0.00', // currency format
207
+ },
208
+ width: 12,
209
+ valueParserCallback: this.excelRegularCellParser.bind(this),
210
+ },
211
+ groupTotalsExcelExportOptions: {
212
+ style: {
213
+ font: { bold: true, italic: true, size: 11.5 },
214
+ format: '$0.00', // currency format
215
+ border: { top: { color: 'FF747474', style: 'thick' } },
216
+ },
217
+ valueParserCallback: this.excelGroupCellParser.bind(this),
218
+ },
219
+ },
220
+ {
221
+ id: 'taxable',
222
+ name: 'Taxable',
223
+ field: 'taxable',
224
+ cssClass: 'text-center',
225
+ sortable: true,
226
+ width: 60,
227
+ filterable: true,
228
+ formatter: Formatters.checkmarkMaterial,
229
+ exportCustomFormatter: (_row, _cell, val) => (val ? '✓' : ''),
230
+ excelExportOptions: {
231
+ style: {
232
+ alignment: { horizontal: 'center' },
233
+ },
234
+ },
235
+ },
236
+ {
237
+ id: 'taxes',
238
+ name: 'Taxes',
239
+ field: 'taxes',
240
+ cssClass: 'text-taxes',
241
+ type: 'number',
242
+ sortable: true,
243
+ width: 70,
244
+ filterable: true,
245
+ formatter: Formatters.multiple,
246
+ groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollarBold,
247
+ params: {
248
+ formatters: [
249
+ (_row, _cell, _value, _coldef, dataContext) => {
250
+ if (dataContext.taxable) {
251
+ return dataContext.price * dataContext.qty * (this.taxRate / 100);
252
+ }
253
+ return null;
254
+ },
255
+ Formatters.dollar,
256
+ ] as Formatter[],
257
+ },
258
+ excelExportOptions: {
259
+ style: {
260
+ font: { outline: true, italic: true, color: 'FFC65911' },
261
+ format: '$0.00', // currency format
262
+ },
263
+ width: 12,
264
+ valueParserCallback: this.excelRegularCellParser.bind(this),
265
+ },
266
+ groupTotalsExcelExportOptions: {
267
+ style: {
268
+ font: { bold: true, italic: true, color: 'FFC65911', size: 11.5 },
269
+ format: '$0.00', // currency format
270
+ border: { top: { color: 'FF747474', style: 'thick' } },
271
+ },
272
+ valueParserCallback: this.excelGroupCellParser.bind(this),
273
+ },
274
+ },
275
+ {
276
+ id: 'total',
277
+ name: 'Total',
278
+ field: 'total',
279
+ type: 'number',
280
+ sortable: true,
281
+ width: 70,
282
+ filterable: true,
283
+ cssClass: 'text-total',
284
+ formatter: Formatters.multiple,
285
+ groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollarBold,
286
+ params: {
287
+ formatters: [
288
+ (_row, _cell, _value, _coldef, dataContext) => {
289
+ let subTotal = dataContext.price * dataContext.qty;
290
+ if (dataContext.taxable) {
291
+ subTotal += subTotal * (this.taxRate / 100);
292
+ }
293
+ return subTotal;
294
+ },
295
+ Formatters.dollar,
296
+ ] as Formatter[],
297
+ },
298
+ excelExportOptions: {
299
+ style: {
300
+ font: { outline: true, bold: true, color: 'FF005A9E' },
301
+ format: '$0.00', // currency format
302
+ },
303
+ width: 12,
304
+ valueParserCallback: this.excelRegularCellParser.bind(this),
305
+ },
306
+ groupTotalsExcelExportOptions: {
307
+ style: {
308
+ font: { bold: true, color: 'FF005A9E', size: 12 },
309
+ format: '$0.00',
310
+ border: { top: { color: 'FF747474', style: 'thick' } },
311
+ },
312
+ valueParserCallback: this.excelGroupCellParser.bind(this),
313
+ },
314
+ },
315
+ ];
316
+
317
+ this.gridOptions = {
318
+ autoAddCustomEditorFormatter: customEditableInputFormatter,
319
+ gridHeight: 410,
320
+ gridWidth: 750,
321
+ enableCellNavigation: true,
322
+ autoEdit: true,
323
+ autoCommitEdit: true,
324
+ editable: true,
325
+ rowHeight: 33,
326
+ formatterOptions: {
327
+ maxDecimal: 2,
328
+ minDecimal: 2,
329
+ },
330
+ enableGrouping: true,
331
+ externalResources: [this.excelExportService],
332
+ enableExcelExport: true,
333
+ excelExportOptions: {
334
+ filename: 'grocery-list',
335
+ sanitizeDataExport: true,
336
+ sheetName: 'Grocery List',
337
+ columnHeaderStyle: {
338
+ font: { color: 'FFFFFFFF' },
339
+ fill: { type: 'pattern', patternType: 'solid', fgColor: 'FF4a6c91' },
340
+ },
341
+
342
+ // optionally pass a custom header to the Excel Sheet
343
+ // a lot of the info can be found on Web Archive of Excel-Builder
344
+ // https://ghiscoding.gitbook.io/excel-builder-vanilla/cookbook/fonts-and-colors
345
+ customExcelHeader: (workbook, sheet) => {
346
+ const excelFormat = workbook.getStyleSheet().createFormat({
347
+ // every color is prefixed with FF, then regular HTML color
348
+ font: { size: 18, fontName: 'Calibri', bold: true, color: 'FFFFFFFF' },
349
+ alignment: { wrapText: true, horizontal: 'center' },
350
+ fill: { type: 'pattern', patternType: 'solid', fgColor: 'FF203764' },
351
+ });
352
+ sheet.setRowInstructions(0, { height: 40 }); // change height of row 0
353
+
354
+ // excel cells start with A1 which is upper left corner
355
+ const customTitle = 'Grocery Shopping List';
356
+ const lastCellMerge = this.isDataGrouped ? 'H1' : 'G1';
357
+ sheet.mergeCells('A1', lastCellMerge);
358
+ sheet.data.push([{ value: customTitle, metadata: { style: excelFormat.id } }]);
359
+ },
360
+ },
361
+ };
362
+ }
363
+
364
+ invalidateAll() {
365
+ // make sure to call both refresh/invalid in this order so that whenever a cell changes we recalculate all Groups
366
+ this.angularGrid.dataView?.refresh();
367
+ this.angularGrid.slickGrid?.invalidate();
368
+ }
369
+
370
+ updateTaxRate() {
371
+ // since Aggregator are cached and we provided the Tax Rate to our custom Aggregator,
372
+ // we need to recompile them by resetting the Group
373
+ if (this.isDataGrouped) {
374
+ this.groupByTaxable();
375
+ }
376
+
377
+ this.invalidateAll();
378
+ }
379
+
380
+ exportToExcel() {
381
+ this.excelExportService.exportToExcel();
382
+ }
383
+
384
+ excelGroupCellParser(totals: SlickGroupTotals, { columnDef, excelFormatId, dataRowIdx }: ExcelGroupValueParserArgs) {
385
+ const colOffset = 0; // col offset of 1x because we skipped 1st column OR 0 offset if we use a Group because the Group column replaces the skip
386
+ const rowOffset = 3; // row offset of 3x because: 1x Title, 1x Headers and Excel row starts at 1 => 3
387
+ const priceIdx = this.angularGrid.slickGrid?.getColumnIndex('price') || 0;
388
+ const qtyIdx = this.angularGrid.slickGrid?.getColumnIndex('qty') || 0;
389
+ const taxesIdx = this.angularGrid.slickGrid?.getColumnIndex('taxes') || 0;
390
+ const subTotalIdx = this.angularGrid.slickGrid?.getColumnIndex('subTotal') || 0;
391
+ const totalIdx = this.angularGrid.slickGrid?.getColumnIndex('total') || 0;
392
+ const groupItemCount = totals?.group?.count || 0;
393
+
394
+ // the code below calculates Excel column position dynamically, technically Price is at "B" and Qty is "C"
395
+ const excelPriceCol = `${String.fromCharCode('A'.charCodeAt(0) + priceIdx - colOffset)}`;
396
+ const excelQtyCol = `${String.fromCharCode('A'.charCodeAt(0) + qtyIdx - colOffset)}`;
397
+ const excelSubTotalCol = `${String.fromCharCode('A'.charCodeAt(0) + subTotalIdx - colOffset)}`;
398
+ const excelTaxesCol = `${String.fromCharCode('A'.charCodeAt(0) + taxesIdx - colOffset)}`;
399
+ const excelTotalCol = `${String.fromCharCode('A'.charCodeAt(0) + totalIdx - colOffset)}`;
400
+
401
+ let excelCol = '';
402
+ switch (columnDef.id) {
403
+ case 'price':
404
+ excelCol = excelPriceCol;
405
+ break;
406
+ case 'qty':
407
+ excelCol = excelQtyCol;
408
+ break;
409
+ case 'subTotal':
410
+ excelCol = excelSubTotalCol;
411
+ break;
412
+ case 'taxes':
413
+ excelCol = excelTaxesCol;
414
+ break;
415
+ case 'total':
416
+ excelCol = excelTotalCol;
417
+ break;
418
+ }
419
+ return {
420
+ value: `SUM(${excelCol}${dataRowIdx + rowOffset - groupItemCount}:${excelCol}${dataRowIdx + rowOffset - 1})`,
421
+ metadata: { type: 'formula', style: excelFormatId },
422
+ };
423
+ }
424
+
425
+ /** We'll use a generic parser to reuse similar logic for all 3 calculable columns (SubTotal, Taxes, Total) */
426
+ excelRegularCellParser(_data: any, { columnDef, excelFormatId, dataRowIdx, dataContext }: ExcelCellValueParserArgs<GroceryItem>) {
427
+ // assuming that we want to calculate: (Price * Qty) => Sub-Total
428
+ const colOffset = !this.isDataGrouped ? 1 : 0; // col offset of 1x because we skipped 1st column OR 0 offset if we use a Group because the Group column replaces the skip
429
+ const rowOffset = 3; // row offset of 3x because: 1x Title, 1x Headers and Excel row starts at 1 => 3
430
+ const priceIdx = this.angularGrid.slickGrid?.getColumnIndex('price') || 0;
431
+ const qtyIdx = this.angularGrid.slickGrid?.getColumnIndex('qty') || 0;
432
+ const taxesIdx = this.angularGrid.slickGrid?.getColumnIndex('taxes') || 0;
433
+
434
+ // the code below calculates Excel column position dynamically, technically Price is at "B" and Qty is "C"
435
+ const excelPriceCol = `${String.fromCharCode('A'.charCodeAt(0) + priceIdx - colOffset)}${dataRowIdx + rowOffset}`;
436
+ const excelQtyCol = `${String.fromCharCode('A'.charCodeAt(0) + qtyIdx - colOffset)}${dataRowIdx + rowOffset}`;
437
+ const excelTaxesCol = `${String.fromCharCode('A'.charCodeAt(0) + taxesIdx - colOffset)}${dataRowIdx + rowOffset}`;
438
+
439
+ // `value` is our Excel cells to calculat (e.g.: "B4*C4")
440
+ // metadata `type` has to be set to "formula" and the `style` is what we defined in `excelExportOptions.style` which is `excelFormatId` in the callback arg
441
+
442
+ let excelVal = '';
443
+ switch (columnDef.id) {
444
+ case 'subTotal':
445
+ excelVal = `${excelPriceCol}*${excelQtyCol}`; // like "C4*D4"
446
+ break;
447
+ case 'taxes':
448
+ excelVal = dataContext.taxable ? `${excelPriceCol}*${excelQtyCol}*${this.taxRate / 100}` : '';
449
+ break;
450
+ case 'total':
451
+ excelVal = `(${excelPriceCol}*${excelQtyCol})+${excelTaxesCol}`;
452
+ break;
453
+ }
454
+ return { value: excelVal, metadata: { type: 'formula', style: excelFormatId } };
455
+ }
456
+
457
+ getData() {
458
+ let i = 1;
459
+ const datasetTmp = [
460
+ { id: i++, name: 'Oranges', qty: 4, taxable: false, price: 2.22 },
461
+ { id: i++, name: 'Apples', qty: 3, taxable: false, price: 1.55 },
462
+ { id: i++, name: 'Honeycomb Cereals', qty: 2, taxable: true, price: 4.55 },
463
+ { id: i++, name: 'Raisins', qty: 77, taxable: false, price: 0.23 },
464
+ { id: i++, name: 'Corn Flake Cereals', qty: 1, taxable: true, price: 6.62 },
465
+ { id: i++, name: 'Tomatoes', qty: 3, taxable: false, price: 1.88 },
466
+ { id: i++, name: 'Butter', qty: 1, taxable: false, price: 3.33 },
467
+ { id: i++, name: 'BBQ Chicken', qty: 1, taxable: false, price: 12.33 },
468
+ { id: i++, name: 'Chicken Wings', qty: 12, taxable: true, price: 0.53 },
469
+ { id: i++, name: 'Drinkable Yogurt', qty: 6, taxable: true, price: 1.22 },
470
+ { id: i++, name: 'Milk', qty: 3, taxable: true, price: 3.11 },
471
+ ] as GroceryItem[];
472
+
473
+ return datasetTmp;
474
+ }
475
+
476
+ clearGrouping() {
477
+ this.isDataGrouped = false;
478
+ this.angularGrid?.dataView?.setGrouping([]);
479
+ }
480
+
481
+ groupByTaxable() {
482
+ const checkIcon = 'mdi-check-box-outline';
483
+ const uncheckIcon = 'mdi-checkbox-blank-outline';
484
+ this.isDataGrouped = true;
485
+
486
+ this.angularGrid?.dataView?.setGrouping({
487
+ getter: 'taxable',
488
+ formatter: (g) =>
489
+ `Taxable: <span class="mdi ${g.value ? checkIcon : uncheckIcon} text-info"></span> <span class="text-primary">(${g.count} items)</span>`,
490
+ comparer: (a, b) => b.value - a.value,
491
+ aggregators: [
492
+ new Aggregators.Sum('price'),
493
+ new Aggregators.Sum('qty'),
494
+ new CustomSumAggregator('subTotal', this.taxRate),
495
+ new CustomSumAggregator('taxes', this.taxRate),
496
+ new CustomSumAggregator('total', this.taxRate),
497
+ ],
498
+ aggregateCollapsed: false,
499
+ lazyTotalsCalculation: false,
500
+ } as Grouping);
501
+
502
+ this.angularGrid?.dataView?.refresh();
503
+ }
504
+ }
@@ -0,0 +1,30 @@
1
+ <div id="demo-container" class="container-fluid">
2
+ <h2>
3
+ Example 37: Footer Totals Row
4
+ <button class="btn btn-outline-secondary btn-sm ms-3" (click)="toggleDarkMode()" data-test="toggle-dark-mode">
5
+ <span class="mdi mdi-theme-light-dark"></span>
6
+ <span>Toggle Dark Mode</span>
7
+ </button>
8
+ <span class="float-end">
9
+ <a
10
+ style="font-size: 18px"
11
+ target="_blank"
12
+ href="https://github.com/ghiscoding/slickgrid-universal/blob/master/frameworks/angular-slickgrid/src/demos/examples/grid-footer-totals.component.ts"
13
+ >
14
+ <span class="mdi mdi-link-variant"></span> code
15
+ </a>
16
+ </span>
17
+ </h2>
18
+ <div class="subtitle">Display a totals row at the end of the grid.</div>
19
+
20
+ <angular-slickgrid
21
+ gridId="grid37"
22
+ [columns]="columnDefinitions"
23
+ [options]="gridOptions"
24
+ [dataset]="dataset"
25
+ (onAngularGridCreated)="angularGridReady($event.detail)"
26
+ (onCellChange)="handleOnCellChange($event.detail.eventData, $event.detail.args)"
27
+ (onColumnsReordered)="handleOnColumnsReordered()"
28
+ >
29
+ </angular-slickgrid>
30
+ </div>
@@ -0,0 +1,123 @@
1
+ import { Component, OnDestroy, OnInit } from '@angular/core';
2
+ import { AngularGridInstance, Column, Editors, GridOption, OnCellChangeEventArgs } from '../../library';
3
+
4
+ const NB_ITEMS = 100;
5
+
6
+ @Component({
7
+ templateUrl: './example37.component.html',
8
+ standalone: false,
9
+ })
10
+ export class Example37Component implements OnDestroy, OnInit {
11
+ private _darkMode = false;
12
+ columnDefinitions: Column[] = [];
13
+ gridOptions!: GridOption;
14
+ dataset!: any[];
15
+ angularGrid!: AngularGridInstance;
16
+
17
+ angularGridReady(angularGrid: AngularGridInstance) {
18
+ this.angularGrid = angularGrid;
19
+ this.updateAllTotals();
20
+ }
21
+
22
+ ngOnInit(): void {
23
+ this.defineGrid();
24
+
25
+ // mock a dataset
26
+ this.dataset = this.loadData(NB_ITEMS);
27
+ }
28
+
29
+ ngOnDestroy() {
30
+ document.querySelector('.panel-wm-content')!.classList.remove('dark-mode');
31
+ document.querySelector<HTMLDivElement>('#demo-container')!.dataset.bsTheme = 'light';
32
+ }
33
+
34
+ /* Define grid Options and Columns */
35
+ defineGrid() {
36
+ const columnDefs: Column[] = [];
37
+ for (let i = 0; i < 10; i++) {
38
+ columnDefs.push({
39
+ id: i,
40
+ name: String.fromCharCode('A'.charCodeAt(0) + i),
41
+ field: String(i),
42
+ type: 'number',
43
+ width: 58,
44
+ editor: { model: Editors.integer },
45
+ });
46
+ }
47
+ this.columnDefinitions = columnDefs;
48
+
49
+ this.gridOptions = {
50
+ autoEdit: true,
51
+ autoCommitEdit: true,
52
+ editable: true,
53
+ darkMode: this._darkMode,
54
+ gridHeight: 450,
55
+ gridWidth: 800,
56
+ enableCellNavigation: true,
57
+ rowHeight: 30,
58
+ createFooterRow: true,
59
+ showFooterRow: true,
60
+ footerRowHeight: 28,
61
+ };
62
+ }
63
+
64
+ loadData(itemCount: number) {
65
+ // mock a dataset
66
+ const datasetTmp: any[] = [];
67
+ for (let i = 0; i < itemCount; i++) {
68
+ const d = (datasetTmp[i] = {} as any);
69
+ d.id = i;
70
+ for (let j = 0; j < this.columnDefinitions.length; j++) {
71
+ d[j] = Math.round(Math.random() * 10);
72
+ }
73
+ }
74
+
75
+ return datasetTmp;
76
+ }
77
+
78
+ handleOnCellChange(_e: Event, args: OnCellChangeEventArgs) {
79
+ this.updateTotal(args.cell);
80
+ }
81
+
82
+ handleOnColumnsReordered() {
83
+ this.updateAllTotals();
84
+ }
85
+
86
+ toggleDarkMode() {
87
+ this._darkMode = !this._darkMode;
88
+ this.toggleBodyBackground();
89
+ this.angularGrid.slickGrid?.setOptions({ darkMode: this._darkMode });
90
+ this.updateAllTotals();
91
+ }
92
+
93
+ toggleBodyBackground() {
94
+ if (this._darkMode) {
95
+ document.querySelector<HTMLDivElement>('.panel-wm-content')!.classList.add('dark-mode');
96
+ document.querySelector<HTMLDivElement>('#demo-container')!.dataset.bsTheme = 'dark';
97
+ } else {
98
+ document.querySelector('.panel-wm-content')!.classList.remove('dark-mode');
99
+ document.querySelector<HTMLDivElement>('#demo-container')!.dataset.bsTheme = 'light';
100
+ }
101
+ }
102
+
103
+ updateAllTotals() {
104
+ let columnIdx = this.angularGrid.slickGrid?.getColumns().length || 0;
105
+ while (columnIdx--) {
106
+ this.updateTotal(columnIdx);
107
+ }
108
+ }
109
+
110
+ updateTotal(cell: number) {
111
+ const columnId = this.angularGrid.slickGrid?.getColumns()[cell].id as number;
112
+
113
+ let total = 0;
114
+ let i = this.dataset.length;
115
+ while (i--) {
116
+ total += parseInt(this.dataset[i][columnId], 10) || 0;
117
+ }
118
+ const columnElement = this.angularGrid.slickGrid?.getFooterRowColumn(columnId);
119
+ if (columnElement) {
120
+ columnElement.textContent = `Sum: ${total}`;
121
+ }
122
+ }
123
+ }