@one-paragon/angular-utilities 2.8.3 → 2.8.4

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 (203) hide show
  1. package/karma.conf.js +43 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +15 -27
  4. package/src/action-state/action-state-spinner/action-state-spinner.component.css +16 -0
  5. package/src/action-state/action-state-spinner/action-state-spinner.component.html +7 -0
  6. package/src/action-state/action-state-spinner/action-state-spinner.component.spec.ts +25 -0
  7. package/src/action-state/action-state-spinner/action-state-spinner.component.ts +26 -0
  8. package/src/action-state/action-state-ui/action-state-ui.module.ts +13 -0
  9. package/src/action-state/index.ts +8 -0
  10. package/src/action-state/ngrx-ext/ngrx-ext.module.ts +14 -0
  11. package/src/action-state/ngrx.ts +69 -0
  12. package/src/http-request-state/RequestStateFactory.ts +56 -0
  13. package/src/http-request-state/RequestStateStore.ts +360 -0
  14. package/src/http-request-state/deprecated.ts +20 -0
  15. package/src/http-request-state/directives/HttpStateDirectiveBase.ts +29 -0
  16. package/src/http-request-state/directives/http-error-state-directive.ts +21 -0
  17. package/src/http-request-state/directives/http-inProgress-state-directive.ts +19 -0
  18. package/src/http-request-state/directives/http-notStarted-state-directive.ts +19 -0
  19. package/src/http-request-state/directives/http-success-state-directive.ts +29 -0
  20. package/src/http-request-state/directives/index.ts +5 -0
  21. package/src/http-request-state/directives/request-state-directive.spec.ts +73 -0
  22. package/src/http-request-state/directives/request-state-directive.ts +78 -0
  23. package/src/http-request-state/documentation/CREATE-REQUESTOR.md +667 -0
  24. package/src/http-request-state/documentation/README.md +191 -0
  25. package/src/http-request-state/documentation/REQUEST-STATE-STORE-CONFIG.md +648 -0
  26. package/src/http-request-state/documentation/REQUESTOR.md +616 -0
  27. package/src/http-request-state/helpers.ts +30 -0
  28. package/src/http-request-state/http-state-module.ts +23 -0
  29. package/src/http-request-state/index.ts +7 -0
  30. package/src/http-request-state/models/view-context.ts +18 -0
  31. package/src/http-request-state/observable.spec.ts +43 -0
  32. package/src/http-request-state/request-state.ts +66 -0
  33. package/src/http-request-state/rxjs/getRequestorBody.ts +10 -0
  34. package/src/http-request-state/rxjs/getRequestorState.ts +8 -0
  35. package/src/http-request-state/rxjs/index.ts +4 -0
  36. package/src/http-request-state/rxjs/tapError.ts +16 -0
  37. package/src/http-request-state/rxjs/tapSuccess.ts +16 -0
  38. package/src/http-request-state/strategies.spec.ts +42 -0
  39. package/src/http-request-state/types.ts +54 -0
  40. package/src/ngrx/actionable-selector.ts +189 -0
  41. package/src/ngrx/index.ts +1 -0
  42. package/src/public-api.ts +40 -0
  43. package/src/rxjs/defaultShareReplay.ts +8 -0
  44. package/src/rxjs/index.ts +5 -0
  45. package/src/rxjs/mapError.ts +8 -0
  46. package/src/rxjs/rxjs-operators.ts +130 -0
  47. package/src/rxjs/subjectifier.ts +17 -0
  48. package/src/rxjs/subscriber.directive.ts +57 -0
  49. package/src/specs/clickSubject.spec.ts +99 -0
  50. package/src/specs/dialog.spec.ts +101 -0
  51. package/src/specs/toggleGroupDirective.spec.ts +229 -0
  52. package/src/table-builder/classes/DefaultSettings.ts +11 -0
  53. package/src/table-builder/classes/MatTableObservableDataSource.ts +23 -0
  54. package/src/table-builder/classes/TableBuilderConfig.ts +49 -0
  55. package/src/table-builder/classes/TableBuilderDataSource.ts +64 -0
  56. package/src/table-builder/classes/TableState.ts +96 -0
  57. package/src/table-builder/classes/data-store.ts +10 -0
  58. package/src/table-builder/classes/display-col.ts +5 -0
  59. package/src/table-builder/classes/filter-info.ts +129 -0
  60. package/src/table-builder/classes/table-builder-general-settings.ts +233 -0
  61. package/src/table-builder/classes/table-builder.ts +105 -0
  62. package/src/table-builder/classes/table-store.helpers.ts +109 -0
  63. package/src/table-builder/classes/table-store.ts +540 -0
  64. package/src/table-builder/components/array-column.component.ts +34 -0
  65. package/src/table-builder/components/column-builder/column-builder.component.html +109 -0
  66. package/src/table-builder/components/column-builder/column-builder.component.scss +43 -0
  67. package/src/table-builder/components/column-builder/column-builder.component.spec.ts +49 -0
  68. package/src/table-builder/components/column-builder/column-builder.component.ts +130 -0
  69. package/src/table-builder/components/column-builder/column-helpers.ts +54 -0
  70. package/src/table-builder/components/column-header-menu/column-header-menu.component.html +128 -0
  71. package/src/table-builder/components/column-header-menu/column-header-menu.component.scss +97 -0
  72. package/src/table-builder/components/column-header-menu/column-header-menu.component.ts +113 -0
  73. package/src/table-builder/components/date-filter/date-filter.component.html +39 -0
  74. package/src/table-builder/components/date-filter/date-filter.component.ts +33 -0
  75. package/src/table-builder/components/date-time-filter/date-time-filter.component.html +25 -0
  76. package/src/table-builder/components/date-time-filter/date-time-filter.component.ts +33 -0
  77. package/src/table-builder/components/filter/filter.component.html +120 -0
  78. package/src/table-builder/components/filter/filter.component.scss +60 -0
  79. package/src/table-builder/components/filter/filter.component.spec.ts +86 -0
  80. package/src/table-builder/components/filter/filter.component.ts +73 -0
  81. package/src/table-builder/components/filter/in-list/in-list-filter.component.ts +171 -0
  82. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.html +60 -0
  83. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.scss +57 -0
  84. package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.ts +44 -0
  85. package/src/table-builder/components/generic-table/generic-table.component.html +140 -0
  86. package/src/table-builder/components/generic-table/generic-table.component.scss +45 -0
  87. package/src/table-builder/components/generic-table/generic-table.component.ts +531 -0
  88. package/src/table-builder/components/generic-table/paginator.component.ts +125 -0
  89. package/src/table-builder/components/group-by-list/group-by-list.component.css +24 -0
  90. package/src/table-builder/components/group-by-list/group-by-list.component.html +21 -0
  91. package/src/table-builder/components/group-by-list/group-by-list.component.spec.ts +23 -0
  92. package/src/table-builder/components/group-by-list/group-by-list.component.ts +26 -0
  93. package/src/table-builder/components/in-filter/in-filter.component.css +22 -0
  94. package/src/table-builder/components/in-filter/in-filter.component.html +38 -0
  95. package/src/table-builder/components/in-filter/in-filter.component.ts +66 -0
  96. package/src/table-builder/components/index.ts +9 -0
  97. package/src/table-builder/components/initialization-component/initialization.component.html +78 -0
  98. package/src/table-builder/components/initialization-component/initialization.component.ts +28 -0
  99. package/src/table-builder/components/link-column.component.ts +42 -0
  100. package/src/table-builder/components/number-filter/number-filter.component.css +10 -0
  101. package/src/table-builder/components/number-filter/number-filter.component.html +32 -0
  102. package/src/table-builder/components/number-filter/number-filter.component.spec.ts +30 -0
  103. package/src/table-builder/components/number-filter/number-filter.component.ts +34 -0
  104. package/src/table-builder/components/profiles-menu/profiles-menu.component.html +77 -0
  105. package/src/table-builder/components/profiles-menu/profiles-menu.component.scss +126 -0
  106. package/src/table-builder/components/profiles-menu/profiles-menu.component.spec.ts +23 -0
  107. package/src/table-builder/components/profiles-menu/profiles-menu.component.ts +64 -0
  108. package/src/table-builder/components/reset-menu/reset-menu.component.css +3 -0
  109. package/src/table-builder/components/reset-menu/reset-menu.component.html +10 -0
  110. package/src/table-builder/components/reset-menu/reset-menu.component.ts +87 -0
  111. package/src/table-builder/components/scroll-strategy.ts +139 -0
  112. package/src/table-builder/components/sort-menu/sort-menu.component-store.ts +57 -0
  113. package/src/table-builder/components/sort-menu/sort-menu.component.html +115 -0
  114. package/src/table-builder/components/sort-menu/sort-menu.component.scss +119 -0
  115. package/src/table-builder/components/sort-menu/sort-menu.component.ts +88 -0
  116. package/src/table-builder/components/table-container/table-container.component.html +94 -0
  117. package/src/table-builder/components/table-container/table-container.component.scss +60 -0
  118. package/src/table-builder/components/table-container/table-container.component.ts +467 -0
  119. package/src/table-builder/components/table-container/table-container.helpers/data-state.helpers.ts +113 -0
  120. package/src/table-builder/components/table-container/table-container.helpers/filter-state.helpers.ts +125 -0
  121. package/src/table-builder/components/table-container/table-container.helpers/groupBy.helpers.ts +172 -0
  122. package/src/table-builder/components/table-container/table-container.helpers/meta-data.helpers.ts +19 -0
  123. package/src/table-builder/components/table-container/table-container.helpers/sort-state.helpers.ts +47 -0
  124. package/src/table-builder/components/table-container/tableProps.ts +21 -0
  125. package/src/table-builder/components/table-container/virtual-scroll-container.ts +216 -0
  126. package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.html +42 -0
  127. package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.ts +47 -0
  128. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.css +40 -0
  129. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.html +11 -0
  130. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.spec.ts +85 -0
  131. package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.ts +35 -0
  132. package/src/table-builder/components/table-container-filter/table-wrapper-filter-store.ts +13 -0
  133. package/src/table-builder/components/table-header-menu/table-header-menu.component.css +21 -0
  134. package/src/table-builder/components/table-header-menu/table-header-menu.component.html +48 -0
  135. package/src/table-builder/components/table-header-menu/table-header-menu.component.ts +36 -0
  136. package/src/table-builder/directives/custom-cell-directive.ts +63 -0
  137. package/src/table-builder/directives/custom-header-directive.ts +16 -0
  138. package/src/table-builder/directives/group-row-directive.ts +91 -0
  139. package/src/table-builder/directives/index.ts +8 -0
  140. package/src/table-builder/directives/multi-sort.directive.spec.ts +124 -0
  141. package/src/table-builder/directives/multi-sort.directive.ts +58 -0
  142. package/src/table-builder/directives/resize-column.directive.ts +107 -0
  143. package/src/table-builder/directives/table-wrapper.directive.ts +13 -0
  144. package/src/table-builder/directives/tb-filter.directive.ts +376 -0
  145. package/src/table-builder/documentation/table-builder/CUSTOM-CELL.md +568 -0
  146. package/src/table-builder/documentation/table-builder/CUSTOM-GROUP-ROW.md +356 -0
  147. package/src/table-builder/documentation/table-builder/METADATA-DOCUMENTATION.md +517 -0
  148. package/src/table-builder/documentation/table-builder/STYLER-STYLE.md +228 -0
  149. package/src/table-builder/documentation/table-builder/TABLE-BUILDER-CONFIG.md +325 -0
  150. package/src/table-builder/documentation/table-builder/TABLE-BUILDER-SETTINGS.md +515 -0
  151. package/src/table-builder/documentation/table-builder/TABLE-BUILDER.md +430 -0
  152. package/src/table-builder/documentation/table-builder/TABLE-CONTAINER.md +628 -0
  153. package/src/table-builder/enums/filterTypes.ts +39 -0
  154. package/src/table-builder/functions/boolean-filter-function.ts +12 -0
  155. package/src/table-builder/functions/date-filter-function.ts +85 -0
  156. package/src/table-builder/functions/download-data.ts +11 -0
  157. package/src/table-builder/functions/null-filter-function.ts +9 -0
  158. package/src/table-builder/functions/number-filter-function.ts +47 -0
  159. package/src/table-builder/functions/sort-data-function.ts +80 -0
  160. package/src/table-builder/functions/string-filter-function.ts +59 -0
  161. package/src/table-builder/interfaces/ColumnInfo.ts +9 -0
  162. package/src/table-builder/interfaces/dictionary.ts +3 -0
  163. package/src/table-builder/interfaces/meta-data.ts +279 -0
  164. package/src/table-builder/ngrx/tableBuilderStateStore.ts +203 -0
  165. package/src/table-builder/pipes/column-total.pipe.ts +16 -0
  166. package/src/table-builder/pipes/format-filter-type.pipe.ts +12 -0
  167. package/src/table-builder/pipes/format-filter-value.pipe.ts +71 -0
  168. package/src/table-builder/pipes/key-display.ts +13 -0
  169. package/src/table-builder/services/all-values-filter-creator.service.ts +92 -0
  170. package/src/table-builder/services/export-to-csv.service.ts +117 -0
  171. package/src/table-builder/services/link-creator.service.ts +98 -0
  172. package/src/table-builder/services/table-template-service.ts +47 -0
  173. package/src/table-builder/services/transform-creator.ts +90 -0
  174. package/src/table-builder/specs/table-custom-filters.spec.ts +262 -0
  175. package/src/table-builder/styles/collapser.styles.scss +16 -0
  176. package/src/table-builder/table-builder.module.ts +42 -0
  177. package/src/table-builder/types/group-types.ts +42 -0
  178. package/src/table-builder/types/index.ts +1 -0
  179. package/src/test.ts +17 -0
  180. package/src/utilities/array-helpers.ts +13 -0
  181. package/src/utilities/directives/auto-focus.directive.ts +20 -0
  182. package/src/utilities/directives/clickEmitterDirective.ts +15 -0
  183. package/src/utilities/directives/clickSubject.ts +19 -0
  184. package/src/utilities/directives/conditional-classes.directive.ts +36 -0
  185. package/src/utilities/directives/dialog-service.ts +19 -0
  186. package/src/utilities/directives/dialog.ts +174 -0
  187. package/src/utilities/directives/mat-toggle-group-directive.ts +60 -0
  188. package/src/utilities/directives/prevent-enter.directive.ts +12 -0
  189. package/src/utilities/directives/stop-propagation.directive.ts +19 -0
  190. package/src/utilities/directives/styler.ts +45 -0
  191. package/src/utilities/directives/trim-whitespace.directive.ts +20 -0
  192. package/src/utilities/index.ts +22 -0
  193. package/src/utilities/module.ts +53 -0
  194. package/src/utilities/pipes/function.pipe.ts +21 -0
  195. package/src/utilities/pipes/phone.pipe.ts +20 -0
  196. package/src/utilities/pipes/space-case.pipes.spec.ts +47 -0
  197. package/src/utilities/pipes/space-case.pipes.ts +29 -0
  198. package/tsconfig.lib.json +20 -0
  199. package/tsconfig.lib.prod.json +10 -0
  200. package/tsconfig.spec.json +17 -0
  201. package/fesm2022/one-paragon-angular-utilities.mjs +0 -7328
  202. package/fesm2022/one-paragon-angular-utilities.mjs.map +0 -1
  203. package/types/one-paragon-angular-utilities.d.ts +0 -2197
@@ -0,0 +1,568 @@
1
+ # CustomCell Directive Documentation
2
+
3
+ ## Overview
4
+
5
+ The `customCell` directive allows you to provide custom templates for rendering table cells. This is useful when you need to display formatted data, add interactive elements, or create complex cell layouts that go beyond simple text display.
6
+
7
+ > **💡 Type Safety Recommendation**: For better TypeScript support and type inference in your templates, it's recommended to use the `tableRef` input parameter. See [customCellTableRef](#customcelltableref) for details.
8
+
9
+ ## Basic Usage
10
+
11
+ ```typescript
12
+ import { Component } from '@angular/core';
13
+ import { TableBuilder, FieldType, CustomCellDirective } from 'angular-utilities';
14
+ import { TableContainerComponent } from 'angular-utilities';
15
+
16
+ @Component({
17
+ selector: 'app-users-table',
18
+ standalone: true,
19
+ imports: [TableContainerComponent, CustomCellDirective],
20
+ template: `
21
+ <tb-table-container [tableBuilder]="tableBuilder">
22
+ <!-- Custom cell template -->
23
+ <p *customCell="'status'; let row">
24
+ <span [class]="'status-badge status-' + row.status">
25
+ {{ row.status }}
26
+ </span>
27
+ </p>
28
+ </tb-table-container>
29
+ `
30
+ })
31
+ export class UsersTableComponent {
32
+ users = [
33
+ { id: 1, name: 'John Doe', status: 'active' },
34
+ { id: 2, name: 'Jane Smith', status: 'inactive' }
35
+ ];
36
+
37
+ tableBuilder = new TableBuilder(this.users);
38
+ }
39
+ ```
40
+
41
+ ## Template Context
42
+
43
+ The custom cell template receives the following context:
44
+
45
+ ### `$implicit` (default)
46
+ - **Type**: `T` (the row data)
47
+ - **Description**: The entire row object. This is the default context variable.
48
+
49
+ ### `element`
50
+ - **Type**: `T` (the row data)
51
+ - **Description**: Alternative named access to the row object.
52
+
53
+ **Example:**
54
+ ```typescript
55
+ <!-- Using $implicit (default) -->
56
+ <p *customCell="'name'; let row">
57
+ {{ row.name }}
58
+ </p>
59
+
60
+ <!-- Using named element -->
61
+ <p *customCell="'name'; let element = element">
62
+ {{ element.name }}
63
+ </p>
64
+ ```
65
+
66
+ ## Directive Inputs
67
+
68
+ ### Required Inputs
69
+
70
+ #### `customCell`
71
+ - **Type**: `string`
72
+ - **Required**: Yes
73
+ - **Description**: The key/name of the column. This must match either:
74
+ - A property key in your data objects
75
+ - A column defined in your metadata
76
+ - A completely custom column (when used with `customCellNotMapped`)
77
+
78
+ **Example:**
79
+ ```html
80
+ <a *customCell="'email'; let row" [href]="'mailto:' + row.email">
81
+ {{ row.email }}
82
+ </a>
83
+ ```
84
+
85
+ ### Optional Inputs
86
+
87
+ #### `customCellDisplayName`
88
+ - **Type**: `string | undefined`
89
+ - **Default**: `undefined`
90
+ - **Description**: The display name for the column header. Overrides the `displayName` from metadata if both are provided.
91
+
92
+ **Example:**
93
+ ```html
94
+ <p *customCell="'fullName'; displayName: 'Employee Name'; let row">
95
+ {{ row.firstName }} {{ row.lastName }}
96
+ </p>
97
+ ```
98
+
99
+ #### `customCellOrder`
100
+ - **Type**: `number | undefined`
101
+ - **Default**: `undefined`
102
+ - **Description**: Controls the column order. Lower numbers appear first. Overrides the `order` from metadata if both are provided.
103
+
104
+ **Example:**
105
+ ```html
106
+ <div *customCell="'actions'; order: 999; let row">
107
+ <button (click)="edit(row)">Edit</button>
108
+ </div>
109
+ ```
110
+
111
+ #### `customCellWidth`
112
+ - **Type**: `string | undefined`
113
+ - **Default**: `undefined`
114
+ - **Description**: CSS width for the column (e.g., `'150px'`, `'20%'`). Overrides the `width` from metadata if both are provided.
115
+
116
+ **Example:**
117
+ ```html
118
+ <span *customCell="'status'; width: '120px'; let row" class="badge">
119
+ {{ row.status }}
120
+ </span>
121
+ ```
122
+
123
+ #### `customCellNotMapped`
124
+ - **Type**: `boolean`
125
+ - **Default**: `false`
126
+ - **Description**: Set to `true` when the column is not mapped to a property in the data source. This is useful for computed columns or action columns that don't correspond to actual data properties. When `true`, the column will have `FieldType.NotMapped`.
127
+
128
+ **Example:**
129
+ ```html
130
+ <!-- Action column not in data -->
131
+ <div *customCell="'actions'; notMapped: true; displayName: 'Actions'; let row">
132
+ <button (click)="edit(row)">Edit</button>
133
+ <button (click)="delete(row)">Delete</button>
134
+ </div>
135
+ ```
136
+
137
+ #### `preSort`
138
+ - **Type**: `SortDef | undefined`
139
+ - **Default**: `undefined`
140
+ - **Description**: Defines initial sorting for this column. Overrides the `preSort` from metadata if both are provided.
141
+
142
+ **Example:**
143
+ ```typescript
144
+ interface SortDef {
145
+ direction: 'asc' | 'desc';
146
+ priority?: number; // For multi-column sort
147
+ }
148
+ ```
149
+
150
+ ```html
151
+ <p *customCell="'createdDate'; preSort: sortDef; let row">
152
+ {{ row.createdDate | date }}
153
+ </p>
154
+
155
+ <!-- In component -->
156
+ sortDef = { direction: 'desc', priority: 1 };
157
+ ```
158
+
159
+ #### `customCellTableRef`
160
+ - **Type**: `TableBuilder<T> | undefined`
161
+ - **Default**: `undefined`
162
+ - **Description**: Reference to the TableBuilder instance for type safety. This helps TypeScript infer the correct type for the row data in the template.
163
+
164
+ **Example:**
165
+ ```typescript
166
+ @Component({
167
+ template: `
168
+ <tb-table-container [tableBuilder]="tableBuilder">
169
+ <p *customCell="'name'; tableRef: tableBuilder; let row">
170
+ <!-- TypeScript now knows row is of type User -->
171
+ {{ row.name }}
172
+ </p>
173
+ </tb-table-container>
174
+ `
175
+ })
176
+ export class UsersTableComponent {
177
+ tableBuilder = new TableBuilder<User>(this.users);
178
+ }
179
+ ```
180
+
181
+ #### `templateRef`
182
+ - **Type**: `TemplateRef<any> | undefined`
183
+ - **Default**: Auto-injected from `ng-template`
184
+ - **Description**: The template reference. This is typically auto-injected and doesn't need to be set manually.
185
+
186
+ ## Combining MetaData with Custom Cells
187
+
188
+ You can define a column in your metadata **and** provide a custom cell template. When both are present:
189
+
190
+ - **The metadata defines** the column's data behavior (field type, sorting, filtering, etc.)
191
+ - **The custom cell template** defines the visual rendering
192
+ - **Custom cell inputs override** matching metadata properties
193
+
194
+ ### Override Priority
195
+
196
+ When a column is defined in both metadata and has a custom cell directive, the directive inputs take precedence:
197
+
198
+ - `customCellDisplayName` → overrides `metaData.displayName`
199
+ - `customCellOrder` → overrides `metaData.order`
200
+ - `customCellWidth` → overrides `metaData.width`
201
+ - `preSort` → overrides `metaData.preSort`
202
+
203
+ ### Example: Metadata + Custom Cell
204
+
205
+ ```typescript
206
+ import { Component } from '@angular/core';
207
+ import { TableBuilder, FieldType } from 'angular-utilities';
208
+
209
+ interface User {
210
+ id: number;
211
+ name: string;
212
+ email: string;
213
+ salary: number;
214
+ status: 'active' | 'inactive' | 'pending';
215
+ }
216
+
217
+ @Component({
218
+ selector: 'app-users-table',
219
+ standalone: true,
220
+ imports: [TableContainerComponent, CustomCellDirective],
221
+ template: `
222
+ <tb-table-container [tableBuilder]="tableBuilder">
223
+ <!-- Email column: metadata defines behavior, custom cell defines rendering -->
224
+ <a *customCell="'email'; let row"
225
+ [href]="'mailto:' + row.email"
226
+ class="email-link">
227
+ <mat-icon>email</mat-icon>
228
+ {{ row.email }}
229
+ </a>
230
+
231
+ <!-- Status column: override display name from metadata -->
232
+ <span *customCell="'status'; displayName: 'Account Status'; let row"
233
+ [class]="'status-badge status-' + row.status">
234
+ {{ row.status | titlecase }}
235
+ </span>
236
+
237
+ <!-- Salary column: metadata provides formatting, custom cell adds styling -->
238
+ <span *customCell="'salary'; let row"
239
+ [class.high-salary]="row.salary > 100000">
240
+ {{ row.salary | currency }}
241
+ </span>
242
+ </tb-table-container>
243
+ `
244
+ })
245
+ export class UsersTableComponent {
246
+ users: User[] = [
247
+ { id: 1, name: 'John Doe', email: 'john@example.com', salary: 95000, status: 'active' },
248
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com', salary: 120000, status: 'active' }
249
+ ];
250
+
251
+ metaData = [
252
+ {
253
+ key: 'id',
254
+ fieldType: FieldType.Number,
255
+ displayName: 'ID',
256
+ width: '80px'
257
+ },
258
+ {
259
+ key: 'name',
260
+ fieldType: FieldType.String,
261
+ displayName: 'Name'
262
+ },
263
+ {
264
+ key: 'email',
265
+ fieldType: FieldType.String,
266
+ displayName: 'Email',
267
+ width: '250px'
268
+ // Custom cell provides the template, but this metadata defines:
269
+ // - Field type (enables proper sorting/filtering)
270
+ // - Default display name (can be overridden by customCellDisplayName)
271
+ // - Width (can be overridden by customCellWidth)
272
+ },
273
+ {
274
+ key: 'salary',
275
+ fieldType: FieldType.Currency,
276
+ displayName: 'Salary',
277
+ width: '120px'
278
+ // FieldType.Currency enables currency-aware sorting
279
+ // Custom cell adds conditional styling
280
+ },
281
+ {
282
+ key: 'status',
283
+ fieldType: FieldType.String,
284
+ displayName: 'Status', // Will be overridden by customCellDisplayName
285
+ order: 50
286
+ }
287
+ ];
288
+
289
+ tableBuilder = new TableBuilder(this.users, this.metaData);
290
+ }
291
+ ```
292
+
293
+ ## Use Cases
294
+
295
+ ### 1. Action Columns
296
+
297
+ ```html
298
+ <div *customCell="'actions'; notMapped: true; displayName: 'Actions'; width: '150px'; order: 999; let row">
299
+ <button mat-icon-button (click)="edit(row)">
300
+ <mat-icon>edit</mat-icon>
301
+ </button>
302
+ <button mat-icon-button (click)="delete(row)">
303
+ <mat-icon>delete</mat-icon>
304
+ </button>
305
+ </div>
306
+ ```
307
+
308
+ ### 2. Status Badges
309
+
310
+ ```html
311
+ <span *customCell="'status'; let row"
312
+ class="status-badge"
313
+ [ngClass]="{
314
+ 'status-active': row.status === 'active',
315
+ 'status-inactive': row.status === 'inactive',
316
+ 'status-pending': row.status === 'pending'
317
+ }">
318
+ {{ row.status | titlecase }}
319
+ </span>
320
+ ```
321
+
322
+ ### 3. Links
323
+
324
+ ```html
325
+ <a *customCell="'name'; let row" [routerLink]="['/users', row.id]">
326
+ {{ row.name }}
327
+ </a>
328
+ ```
329
+
330
+ ### 4. Images
331
+
332
+ ```html
333
+ <img *customCell="'avatar'; width: '80px'; let row"
334
+ [src]="row.avatarUrl"
335
+ [alt]="row.name"
336
+ class="avatar-img">
337
+ ```
338
+
339
+ ### 5. Complex Formatting
340
+
341
+ ```html
342
+ <div *customCell="'address'; let row" class="address-cell">
343
+ <div>{{ row.street }}</div>
344
+ <div>{{ row.city }}, {{ row.state }} {{ row.zip }}</div>
345
+ </div>
346
+ ```
347
+
348
+ ### 6. Conditional Display
349
+
350
+ ```html
351
+ <span *customCell="'discount'; let row">
352
+ @if (row.discount > 0) {
353
+ <span class="discount">{{ row.discount }}% OFF</span>
354
+ } @else {
355
+ <span class="no-discount">Regular Price</span>
356
+ }
357
+ </span>
358
+ ```
359
+
360
+ ### 7. Interactive Elements
361
+
362
+ ```html
363
+ <div *customCell="'quantity'; let row">
364
+ <button (click)="decrement(row)">-</button>
365
+ <span>{{ row.quantity }}</span>
366
+ <button (click)="increment(row)">+</button>
367
+ </div>
368
+ ```
369
+
370
+ ### 8. Computed Values
371
+
372
+ ```html
373
+ <span *customCell="'fullName'; notMapped: true; displayName: 'Full Name'; let row">
374
+ {{ row.firstName }} {{ row.lastName }}
375
+ </span>
376
+ ```
377
+
378
+ ## Important Notes
379
+
380
+ ### Export Behavior
381
+ Custom cells are automatically excluded from CSV exports (`noExport: true`). The export will use the raw data value if the column is mapped to a data property, or exclude the column entirely if `customCellNotMapped` is true.
382
+
383
+ ### Field Type
384
+ - If `customCellNotMapped` is `true`, the field type is set to `FieldType.NotMapped`
385
+ - Otherwise, it's set to `FieldType.Unknown`
386
+ - When combining with metadata, the metadata's field type takes precedence for sorting/filtering behavior
387
+
388
+ ### Type Safety
389
+ For better TypeScript support in templates, use the `customCellTableRef` input:
390
+
391
+ ```typescript
392
+ <p *customCell="'name'; tableRef: tableBuilder; let row">
393
+ <!-- TypeScript will infer the correct type for 'row' -->
394
+ {{ row.name }}
395
+ </p>
396
+ ```
397
+
398
+ ## Complete Example
399
+
400
+ ```typescript
401
+ import { Component } from '@angular/core';
402
+ import { TableBuilder, FieldType, CustomCellDirective } from 'angular-utilities';
403
+ import { TableContainerComponent } from 'angular-utilities';
404
+ import { MatIconModule } from '@angular/material/icon';
405
+ import { MatButtonModule } from '@angular/material/button';
406
+ import { RouterLink } from '@angular/router';
407
+ import { DatePipe, CurrencyPipe, TitleCasePipe } from '@angular/common';
408
+
409
+ interface Product {
410
+ id: number;
411
+ name: string;
412
+ price: number;
413
+ category: string;
414
+ stock: number;
415
+ imageUrl: string;
416
+ status: 'available' | 'out-of-stock' | 'discontinued';
417
+ lastUpdated: Date;
418
+ }
419
+
420
+ @Component({
421
+ selector: 'app-products-table',
422
+ standalone: true,
423
+ imports: [
424
+ TableContainerComponent,
425
+ CustomCellDirective,
426
+ MatIconModule,
427
+ MatButtonModule,
428
+ RouterLink,
429
+ DatePipe,
430
+ CurrencyPipe,
431
+ TitleCasePipe
432
+ ],
433
+ template: `
434
+ <tb-table-container [tableBuilder]="tableBuilder">
435
+ <!-- Image column (not in original data structure) -->
436
+ <img *customCell="'image'; notMapped: true; displayName: 'Product Image'; width: '100px'; order: 0; let row"
437
+ [src]="row.imageUrl"
438
+ [alt]="row.name"
439
+ class="product-image">
440
+
441
+ <!-- Name with link -->
442
+ <a *customCell="'name'; let row" [routerLink]="['/products', row.id]">
443
+ {{ row.name }}
444
+ </a>
445
+
446
+ <!-- Status badge (override display name) -->
447
+ <span *customCell="'status'; displayName: 'Availability'; let row"
448
+ [class]="'status-badge status-' + row.status">
449
+ {{ row.status | titlecase }}
450
+ </span>
451
+
452
+ <!-- Stock with warning indicator -->
453
+ <span *customCell="'stock'; let row" [class.low-stock]="row.stock < 10">
454
+ {{ row.stock }}
455
+ @if (row.stock < 10) {
456
+ <mat-icon class="warning-icon">warning</mat-icon>
457
+ }
458
+ </span>
459
+
460
+ <!-- Actions (not mapped to data) -->
461
+ <div *customCell="'actions'; notMapped: true; displayName: 'Actions'; width: '150px'; order: 999; let row">
462
+ <button mat-icon-button (click)="edit(row)">
463
+ <mat-icon>edit</mat-icon>
464
+ </button>
465
+ <button mat-icon-button (click)="duplicate(row)">
466
+ <mat-icon>content_copy</mat-icon>
467
+ </button>
468
+ <button mat-icon-button (click)="delete(row)" [disabled]="row.status === 'discontinued'">
469
+ <mat-icon>delete</mat-icon>
470
+ </button>
471
+ </div>
472
+ </tb-table-container>
473
+ `,
474
+ styles: [`
475
+ .product-image {
476
+ width: 60px;
477
+ height: 60px;
478
+ object-fit: cover;
479
+ border-radius: 4px;
480
+ }
481
+
482
+ .status-badge {
483
+ padding: 4px 8px;
484
+ border-radius: 12px;
485
+ font-size: 12px;
486
+ font-weight: 500;
487
+ }
488
+
489
+ .status-available { background: #e8f5e9; color: #2e7d32; }
490
+ .status-out-of-stock { background: #fff3e0; color: #e65100; }
491
+ .status-discontinued { background: #ffebee; color: #c62828; }
492
+
493
+ .low-stock {
494
+ color: #e65100;
495
+ display: flex;
496
+ align-items: center;
497
+ gap: 4px;
498
+ }
499
+
500
+ .warning-icon {
501
+ font-size: 16px;
502
+ width: 16px;
503
+ height: 16px;
504
+ }
505
+ `]
506
+ })
507
+ export class ProductsTableComponent {
508
+ products: Product[] = [
509
+ {
510
+ id: 1,
511
+ name: 'Laptop Pro',
512
+ price: 1299.99,
513
+ category: 'Electronics',
514
+ stock: 45,
515
+ imageUrl: '/assets/laptop.jpg',
516
+ status: 'available',
517
+ lastUpdated: new Date('2024-11-15')
518
+ },
519
+ {
520
+ id: 2,
521
+ name: 'Wireless Mouse',
522
+ price: 29.99,
523
+ category: 'Accessories',
524
+ stock: 5,
525
+ imageUrl: '/assets/mouse.jpg',
526
+ status: 'available',
527
+ lastUpdated: new Date('2024-11-20')
528
+ }
529
+ ];
530
+
531
+ metaData = [
532
+ { key: 'id', fieldType: FieldType.Number, displayName: 'ID', width: '80px', order: 1 },
533
+ { key: 'name', fieldType: FieldType.String, displayName: 'Product Name', order: 2 },
534
+ { key: 'price', fieldType: FieldType.Currency, displayName: 'Price', width: '120px', order: 3 },
535
+ { key: 'category', fieldType: FieldType.String, displayName: 'Category', order: 4 },
536
+ { key: 'stock', fieldType: FieldType.Number, displayName: 'Stock', width: '100px', order: 5 },
537
+ { key: 'status', fieldType: FieldType.String, displayName: 'Status', order: 6 },
538
+ { key: 'lastUpdated', fieldType: FieldType.Date, displayName: 'Last Updated', order: 7 }
539
+ ];
540
+
541
+ tableBuilder = new TableBuilder(this.products, this.metaData, {
542
+ tableSettings: {
543
+ tableId: 'products-table',
544
+ trackBy: 'id'
545
+ }
546
+ });
547
+
548
+ edit(product: Product) {
549
+ console.log('Edit:', product);
550
+ }
551
+
552
+ duplicate(product: Product) {
553
+ console.log('Duplicate:', product);
554
+ }
555
+
556
+ delete(product: Product) {
557
+ console.log('Delete:', product);
558
+ }
559
+ }
560
+ ```
561
+
562
+ ## Related Documentation
563
+
564
+ - [Table Container Component](TABLE-CONTAINER.md) - How to use custom cells with the table container
565
+ - [MetaData Documentation](METADATA-DOCUMENTATION.md) - Column configuration that works with custom cells
566
+ - [TableBuilder Documentation](TABLE-BUILDER.md) - Setting up the table builder
567
+ - [TableBuilder Settings](TABLE-BUILDER-SETTINGS.md) - Table behavior and appearance
568
+ - [CustomGroupRow Directive](CUSTOM-GROUP-ROW.md) - Custom group row templates