ngx-st-tables 18.0.19 → 18.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1201 -114
- package/esm2022/lib/components/material-table/material-table-row-cell/material-table-row-cell.component.mjs +6 -5
- package/esm2022/lib/models/st-material-table-column.model.mjs +1 -1
- package/fesm2022/ngx-st-tables.mjs +5 -4
- package/fesm2022/ngx-st-tables.mjs.map +1 -1
- package/lib/models/st-material-table-column.model.d.ts +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,153 +1,1240 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Material Table Component - Complete Input/Output Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Overview](#overview)
|
|
5
|
+
- [Basic Inputs](#basic-inputs)
|
|
6
|
+
- [Display & Layout Inputs](#display--layout-inputs)
|
|
7
|
+
- [Data Management Inputs](#data-management-inputs)
|
|
8
|
+
- [Row Selection Inputs](#row-selection-inputs)
|
|
9
|
+
- [Row Editing Inputs](#row-editing-inputs)
|
|
10
|
+
- [Row Actions Inputs](#row-actions-inputs)
|
|
11
|
+
- [Column Configuration](#column-configuration)
|
|
12
|
+
- [Outputs (Events)](#outputs-events)
|
|
13
|
+
- [Usage Examples](#usage-examples)
|
|
4
14
|
|
|
5
|
-
|
|
15
|
+
---
|
|
6
16
|
|
|
7
|
-
|
|
17
|
+
## Overview
|
|
8
18
|
|
|
9
|
-
The table
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
19
|
+
The `ngx-st-material-table` component is a powerful Angular Material table with features including:
|
|
20
|
+
- Pagination, sorting, and filtering
|
|
21
|
+
- Lazy loading support
|
|
22
|
+
- Row editing (inline editing or auto-save)
|
|
23
|
+
- Row selection (single or multiple)
|
|
24
|
+
- Custom column templates
|
|
25
|
+
- Expandable rows
|
|
26
|
+
- Local storage persistence
|
|
27
|
+
- Create, update, and delete operations
|
|
14
28
|
|
|
15
|
-
|
|
29
|
+
---
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
// Parent Component
|
|
19
|
-
@Component({
|
|
20
|
-
selector: 'app-example',
|
|
21
|
-
template: `
|
|
22
|
-
<ngx-st-material-table
|
|
23
|
-
[data]="tableData"
|
|
24
|
-
[initColumns]="columns"
|
|
25
|
-
[allowEditRow]="true"
|
|
26
|
-
[createButtonUseAddRow]="true"
|
|
27
|
-
(saveNewCreatedRow)="onSaveNewCreatedRow($event)"
|
|
28
|
-
(saveNewRow)="onSaveEditedRow($event)"
|
|
29
|
-
/>
|
|
30
|
-
`
|
|
31
|
-
})
|
|
32
|
-
export class ExampleComponent {
|
|
33
|
-
tableData: any[] = [];
|
|
34
|
-
|
|
35
|
-
columns: StMaterialTableColumnModel[] = [
|
|
36
|
-
{ field: 'name', header: 'Name', allowEditColumn: true, editColumnRequired: true },
|
|
37
|
-
{ field: 'email', header: 'Email', allowEditColumn: true },
|
|
38
|
-
];
|
|
31
|
+
## Basic Inputs
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
### `tableTitle`
|
|
34
|
+
- **Type:** `string`
|
|
35
|
+
- **Default:** `''`
|
|
36
|
+
- **Description:** Title displayed at the top of the table in the caption area.
|
|
37
|
+
- **Example:**
|
|
38
|
+
```typescript
|
|
39
|
+
tableTitle="Users List"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### `pageSize`
|
|
43
|
+
- **Type:** `number`
|
|
44
|
+
- **Default:** `10`
|
|
45
|
+
- **Description:** Number of rows to display per page.
|
|
46
|
+
- **Example:**
|
|
47
|
+
```typescript
|
|
48
|
+
[pageSize]="25"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `dataLength`
|
|
52
|
+
- **Type:** `number`
|
|
53
|
+
- **Default:** `0`
|
|
54
|
+
- **Description:** Total number of records (used for lazy loading pagination). Only needed when `lazyLoading` is true.
|
|
55
|
+
- **Example:**
|
|
56
|
+
```typescript
|
|
57
|
+
[dataLength]="totalRecords"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### `data`
|
|
61
|
+
- **Type:** `any[]`
|
|
62
|
+
- **Default:** `[]`
|
|
63
|
+
- **Description:** Array of data objects to display in the table. Each object represents one row.
|
|
64
|
+
- **Important:** Uses immutable data pattern. Always pass a new array reference when updating data.
|
|
65
|
+
- **Example:**
|
|
66
|
+
```typescript
|
|
67
|
+
[data]="users"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### `initColumns`
|
|
71
|
+
- **Type:** `StMaterialTableColumnModel[]`
|
|
72
|
+
- **Default:** `[]`
|
|
73
|
+
- **Description:** Array of column definitions that configure how each column is displayed and behaves.
|
|
74
|
+
- **See:** [Column Configuration](#column-configuration) section for details.
|
|
75
|
+
- **Example:**
|
|
76
|
+
```typescript
|
|
77
|
+
[initColumns]="columnDefs"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Display & Layout Inputs
|
|
83
|
+
|
|
84
|
+
### `showGlobalSearch`
|
|
85
|
+
- **Type:** `boolean`
|
|
86
|
+
- **Default:** `false`
|
|
87
|
+
- **Description:** Shows a global search input that searches across all visible columns.
|
|
88
|
+
- **Example:**
|
|
89
|
+
```typescript
|
|
90
|
+
[showGlobalSearch]="true"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `allowPickColumns`
|
|
94
|
+
- **Type:** `boolean`
|
|
95
|
+
- **Default:** `false`
|
|
96
|
+
- **Description:** Allows users to show/hide columns via a column picker dialog.
|
|
97
|
+
- **Example:**
|
|
98
|
+
```typescript
|
|
99
|
+
[allowPickColumns]="true"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `allowReorderColumns`
|
|
103
|
+
- **Type:** `boolean`
|
|
104
|
+
- **Default:** `false`
|
|
105
|
+
- **Description:** Allows users to reorder columns by dragging them.
|
|
106
|
+
- **Example:**
|
|
107
|
+
```typescript
|
|
108
|
+
[allowReorderColumns]="true"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `localStorageName`
|
|
112
|
+
- **Type:** `string`
|
|
113
|
+
- **Default:** `''`
|
|
114
|
+
- **Description:** Key name for storing table state (pagination, sorting, filters, column order) in localStorage. If empty, state is not persisted.
|
|
115
|
+
- **Example:**
|
|
116
|
+
```typescript
|
|
117
|
+
localStorageName="users-table-state"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `isLoading`
|
|
121
|
+
- **Type:** `boolean`
|
|
122
|
+
- **Default:** `false`
|
|
123
|
+
- **Description:** Shows a loading spinner overlay on the table.
|
|
124
|
+
- **Example:**
|
|
125
|
+
```typescript
|
|
126
|
+
[isLoading]="loading"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `extraCustomFilter`
|
|
130
|
+
- **Type:** `TemplateRef<any>`
|
|
131
|
+
- **Default:** `undefined`
|
|
132
|
+
- **Description:** Custom template for additional filter controls displayed in the table caption area.
|
|
133
|
+
- **Example:**
|
|
134
|
+
```html
|
|
135
|
+
<ng-template #customFilters>
|
|
136
|
+
<mat-form-field>
|
|
137
|
+
<mat-select placeholder="Status">
|
|
138
|
+
<mat-option value="active">Active</mat-option>
|
|
139
|
+
<mat-option value="inactive">Inactive</mat-option>
|
|
140
|
+
</mat-select>
|
|
141
|
+
</mat-form-field>
|
|
142
|
+
</ng-template>
|
|
143
|
+
|
|
144
|
+
[extraCustomFilter]="customFilters"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Data Management Inputs
|
|
150
|
+
|
|
151
|
+
### `lazyLoading`
|
|
152
|
+
- **Type:** `boolean`
|
|
153
|
+
- **Default:** `false`
|
|
154
|
+
- **Description:** Enables server-side pagination, sorting, and filtering. When true, table emits `loadData` events instead of handling data locally.
|
|
155
|
+
- **Required with:** `dataLength` input must be provided
|
|
156
|
+
- **Example:**
|
|
157
|
+
```typescript
|
|
158
|
+
[lazyLoading]="true"
|
|
159
|
+
[dataLength]="totalRecords"
|
|
160
|
+
(loadData)="onLoadData($event)"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `setNewDataWithoutRefresh`
|
|
164
|
+
- **Type:** `boolean`
|
|
165
|
+
- **Default:** `false`
|
|
166
|
+
- **Description:** When true and data array length hasn't changed, updates existing row objects in place without recreating table rows. This preserves focus state during editing and prevents UI flickering.
|
|
167
|
+
- **Use case:** Ideal for real-time updates or auto-save scenarios where you frequently update data.
|
|
168
|
+
- **Example:**
|
|
169
|
+
```typescript
|
|
170
|
+
[setNewDataWithoutRefresh]="true"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Row Selection Inputs
|
|
176
|
+
|
|
177
|
+
### `allowSelectRow`
|
|
178
|
+
- **Type:** `boolean`
|
|
179
|
+
- **Default:** `false`
|
|
180
|
+
- **Description:** Enables row selection with checkboxes. Adds a selection column to the left of the table.
|
|
181
|
+
- **Example:**
|
|
182
|
+
```typescript
|
|
183
|
+
[allowSelectRow]="true"
|
|
184
|
+
(selectRowChange)="onSelectionChange($event)"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### `selectionFieldLabel`
|
|
188
|
+
- **Type:** `string`
|
|
189
|
+
- **Default:** `''`
|
|
190
|
+
- **Description:** Property name from the row object to use as the display label for selected rows (shown in chips).
|
|
191
|
+
- **Example:**
|
|
192
|
+
```typescript
|
|
193
|
+
selectionFieldLabel="name"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### `selectRowOnlyOne`
|
|
197
|
+
- **Type:** `boolean`
|
|
198
|
+
- **Default:** `false`
|
|
199
|
+
- **Description:** When true, only one row can be selected at a time (radio button behavior instead of checkboxes).
|
|
200
|
+
- **Example:**
|
|
201
|
+
```typescript
|
|
202
|
+
[selectRowOnlyOne]="true"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `selectRowValueDisplay`
|
|
206
|
+
- **Type:** `(row: any) => string`
|
|
207
|
+
- **Default:** `undefined`
|
|
208
|
+
- **Description:** Custom formatter function to generate the display value for selected rows. Takes precedence over `selectionFieldLabel`.
|
|
209
|
+
- **Use case:** When you need to display multiple fields or apply custom formatting.
|
|
210
|
+
- **Example:**
|
|
211
|
+
```typescript
|
|
212
|
+
[selectRowValueDisplay]="formatSelectedRow"
|
|
213
|
+
|
|
214
|
+
formatSelectedRow(row: any): string {
|
|
215
|
+
return `${row.firstName} ${row.lastName} (${row.email})`;
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### `initSelectedRow`
|
|
220
|
+
- **Type:** `any` or `any[]`
|
|
221
|
+
- **Default:** `undefined`
|
|
222
|
+
- **Description:** Pre-selected row(s) when the table initializes.
|
|
223
|
+
- **Example:**
|
|
224
|
+
```typescript
|
|
225
|
+
[initSelectedRow]="preSelectedUsers"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Row Editing Inputs
|
|
231
|
+
|
|
232
|
+
### `allowEditRow`
|
|
233
|
+
- **Type:** `boolean`
|
|
234
|
+
- **Default:** `false`
|
|
235
|
+
- **Description:** Enables inline row editing. Adds edit/delete action buttons to each row (unless `autoSaveOnChange` is true).
|
|
236
|
+
- **Note:** Columns must have `allowEditColumn: true` to be editable.
|
|
237
|
+
- **Example:**
|
|
238
|
+
```typescript
|
|
239
|
+
[allowEditRow]="true"
|
|
240
|
+
(saveEditedRow)="onRowSaved($event)"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `allowEditInEditRow`
|
|
244
|
+
- **Type:** `boolean`
|
|
245
|
+
- **Default:** `true`
|
|
246
|
+
- **Description:** Shows the edit button in the actions column. Set to false to hide it while still allowing editing functionality.
|
|
247
|
+
- **Example:**
|
|
248
|
+
```typescript
|
|
249
|
+
[allowEditInEditRow]="false"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### `allowDeleteInEditRow`
|
|
253
|
+
- **Type:** `boolean`
|
|
254
|
+
- **Default:** `true`
|
|
255
|
+
- **Description:** Shows the delete button in the actions column.
|
|
256
|
+
- **Example:**
|
|
257
|
+
```typescript
|
|
258
|
+
[allowDeleteInEditRow]="false"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### `showEditAllRows`
|
|
262
|
+
- **Type:** `boolean`
|
|
263
|
+
- **Default:** `false`
|
|
264
|
+
- **Description:** Shows a button in the table caption that toggles edit mode for all rows simultaneously.
|
|
265
|
+
- **Example:**
|
|
266
|
+
```typescript
|
|
267
|
+
[showEditAllRows]="true"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### `autoSaveOnChange`
|
|
271
|
+
- **Type:** `boolean`
|
|
272
|
+
- **Default:** `false`
|
|
273
|
+
- **Description:** When true, field changes are saved immediately without requiring save/cancel buttons. Perfect for quantity inputs, toggles, or selection tables where instant updates are needed.
|
|
274
|
+
- **Behavior:**
|
|
275
|
+
- Removes save/cancel buttons from the table
|
|
276
|
+
- Emits `fieldValueChanged` event on every field change
|
|
277
|
+
- Parent should update their data source immediately
|
|
278
|
+
- **Example:**
|
|
279
|
+
```typescript
|
|
280
|
+
[autoSaveOnChange]="true"
|
|
281
|
+
(fieldValueChanged)="onFieldChanged($event)"
|
|
282
|
+
|
|
283
|
+
onFieldChanged(event: { row: any; field: string; value: any; index: number }) {
|
|
284
|
+
// Update your data source
|
|
285
|
+
this.users[event.index][event.field] = event.value;
|
|
286
|
+
// Optionally call API to persist
|
|
287
|
+
this.updateUser(event.row);
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### `canEditRowValidator`
|
|
292
|
+
- **Type:** `(row: any) => boolean`
|
|
293
|
+
- **Default:** `() => true`
|
|
294
|
+
- **Description:** Function to determine if a specific row can be edited. Return false to disable editing for that row.
|
|
295
|
+
- **Example:**
|
|
296
|
+
```typescript
|
|
297
|
+
[canEditRowValidator]="canEditUser"
|
|
298
|
+
|
|
299
|
+
canEditUser(row: any): boolean {
|
|
300
|
+
return row.status !== 'archived' && row.isEditable;
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### `canDeleteRowValidator`
|
|
305
|
+
- **Type:** `(row: any) => boolean`
|
|
306
|
+
- **Default:** `() => true`
|
|
307
|
+
- **Description:** Function to determine if a specific row can be deleted. Return false to disable delete button for that row.
|
|
308
|
+
- **Example:**
|
|
309
|
+
```typescript
|
|
310
|
+
[canDeleteRowValidator]="canDeleteUser"
|
|
311
|
+
|
|
312
|
+
canDeleteUser(row: any): boolean {
|
|
313
|
+
return row.status !== 'system' && !row.hasRelatedRecords;
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Row Actions Inputs
|
|
320
|
+
|
|
321
|
+
### `rowClickAction`
|
|
322
|
+
- **Type:** `(row: any) => void`
|
|
323
|
+
- **Default:** `undefined`
|
|
324
|
+
- **Description:** Function called when a row is clicked (only if `allowSelectRow` and `allowExtendRow` are false).
|
|
325
|
+
- **Example:**
|
|
326
|
+
```typescript
|
|
327
|
+
[rowClickAction]="onRowClick"
|
|
328
|
+
|
|
329
|
+
onRowClick(row: any): void {
|
|
330
|
+
this.router.navigate(['/users', row.id]);
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### `allowCreateRow`
|
|
335
|
+
- **Type:** `boolean`
|
|
336
|
+
- **Default:** `false`
|
|
337
|
+
- **Description:** Shows an "Add New Row" button below the table that adds a new editable row.
|
|
338
|
+
- **Example:**
|
|
339
|
+
```typescript
|
|
340
|
+
[allowCreateRow]="true"
|
|
341
|
+
(saveCreatedRow)="onRowCreated($event)"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### `showCreateButton`
|
|
345
|
+
- **Type:** `boolean`
|
|
346
|
+
- **Default:** `false`
|
|
347
|
+
- **Description:** Shows a custom create button in the table caption (separate from `allowCreateRow`).
|
|
348
|
+
- **Example:**
|
|
349
|
+
```typescript
|
|
350
|
+
[showCreateButton]="true"
|
|
351
|
+
[createButtonLabel]="'Add User'"
|
|
352
|
+
[createButtonAction]="openCreateDialog"
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### `createButtonLabel`
|
|
356
|
+
- **Type:** `string`
|
|
357
|
+
- **Default:** `'Create'`
|
|
358
|
+
- **Description:** Label text for the create button (when `showCreateButton` is true).
|
|
359
|
+
- **Example:**
|
|
360
|
+
```typescript
|
|
361
|
+
createButtonLabel="Add New User"
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### `createButtonAction`
|
|
365
|
+
- **Type:** `() => void`
|
|
366
|
+
- **Default:** `() => {}`
|
|
367
|
+
- **Description:** Function called when the create button is clicked.
|
|
368
|
+
- **Example:**
|
|
369
|
+
```typescript
|
|
370
|
+
[createButtonAction]="openCreateDialog"
|
|
371
|
+
|
|
372
|
+
openCreateDialog(): void {
|
|
373
|
+
// Open a dialog or navigate to create page
|
|
48
374
|
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### `disableCreateButton`
|
|
378
|
+
- **Type:** `boolean`
|
|
379
|
+
- **Default:** `false`
|
|
380
|
+
- **Description:** Disables the create button.
|
|
381
|
+
- **Example:**
|
|
382
|
+
```typescript
|
|
383
|
+
[disableCreateButton]="!hasPermission"
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
49
387
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
388
|
+
## Row Expansion Inputs
|
|
389
|
+
|
|
390
|
+
### `allowExtendRow`
|
|
391
|
+
- **Type:** `boolean`
|
|
392
|
+
- **Default:** `false`
|
|
393
|
+
- **Description:** Enables expandable rows with a toggle button. Clicking a row expands/collapses its detail view.
|
|
394
|
+
- **Required with:** `extendedRowTemplate` must be provided.
|
|
395
|
+
- **Example:**
|
|
396
|
+
```typescript
|
|
397
|
+
[allowExtendRow]="true"
|
|
398
|
+
[extendedRowTemplate]="detailTemplate"
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### `extendedRowTemplate`
|
|
402
|
+
- **Type:** `TemplateRef<{ data: any }>`
|
|
403
|
+
- **Default:** `undefined`
|
|
404
|
+
- **Description:** Template for the expanded row content. Receives the row data via context.
|
|
405
|
+
- **Example:**
|
|
406
|
+
```html
|
|
407
|
+
<ng-template #detailTemplate let-data="data">
|
|
408
|
+
<div class="row-details">
|
|
409
|
+
<h3>User Details</h3>
|
|
410
|
+
<p><strong>Email:</strong> {{ data.email }}</p>
|
|
411
|
+
<p><strong>Phone:</strong> {{ data.phone }}</p>
|
|
412
|
+
<p><strong>Address:</strong> {{ data.address }}</p>
|
|
413
|
+
</div>
|
|
414
|
+
</ng-template>
|
|
415
|
+
|
|
416
|
+
[extendedRowTemplate]="detailTemplate"
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Column Configuration
|
|
422
|
+
|
|
423
|
+
Columns are configured via the `initColumns` input using the `StMaterialTableColumnModel` interface.
|
|
424
|
+
|
|
425
|
+
### Column Model Properties
|
|
426
|
+
|
|
427
|
+
#### Basic Properties
|
|
428
|
+
|
|
429
|
+
##### `field`
|
|
430
|
+
- **Type:** `string`
|
|
431
|
+
- **Required:** Yes
|
|
432
|
+
- **Description:** Property name from the data object to display in this column.
|
|
433
|
+
- **Example:** `field: 'firstName'`
|
|
434
|
+
|
|
435
|
+
##### `header`
|
|
436
|
+
- **Type:** `string`
|
|
437
|
+
- **Required:** Yes
|
|
438
|
+
- **Description:** Column header text displayed in the table header.
|
|
439
|
+
- **Example:** `header: 'First Name'`
|
|
440
|
+
|
|
441
|
+
##### `type`
|
|
442
|
+
- **Type:** `StMaterialColumnType`
|
|
443
|
+
- **Options:** `'string'` | `'number'` | `'boolean'` | `'date'` | `'custom-template'` | `'actions'`
|
|
444
|
+
- **Default:** `'string'`
|
|
445
|
+
- **Description:** Data type of the column, affects display formatting and default filter/edit types.
|
|
446
|
+
- **Example:** `type: 'date'`
|
|
447
|
+
|
|
448
|
+
##### `width`
|
|
449
|
+
- **Type:** `string`
|
|
450
|
+
- **Default:** Auto
|
|
451
|
+
- **Description:** CSS width value for the column.
|
|
452
|
+
- **Example:** `width: '150px'` or `width: '20%'`
|
|
453
|
+
|
|
454
|
+
##### `flexRight`
|
|
455
|
+
- **Type:** `boolean`
|
|
456
|
+
- **Default:** `false`
|
|
457
|
+
- **Description:** Aligns column content to the right.
|
|
458
|
+
- **Example:** `flexRight: true`
|
|
459
|
+
|
|
460
|
+
#### Sorting & Filtering
|
|
461
|
+
|
|
462
|
+
##### `sort`
|
|
463
|
+
- **Type:** `boolean`
|
|
464
|
+
- **Default:** `true`
|
|
465
|
+
- **Description:** Enables sorting for this column.
|
|
466
|
+
- **Example:** `sort: false`
|
|
467
|
+
|
|
468
|
+
##### `filter`
|
|
469
|
+
- **Type:** `boolean`
|
|
470
|
+
- **Default:** `true`
|
|
471
|
+
- **Description:** Enables filtering for this column.
|
|
472
|
+
- **Example:** `filter: true`
|
|
473
|
+
|
|
474
|
+
##### `filterType`
|
|
475
|
+
- **Type:** `StMaterialColumnFilterType`
|
|
476
|
+
- **Options:** `'string'` | `'number'` | `'boolean'` | `'date'` | `'custom'`
|
|
477
|
+
- **Default:** Auto-detected from `type`
|
|
478
|
+
- **Description:** Type of filter input to show for this column.
|
|
479
|
+
- **Example:** `filterType: 'date'`
|
|
480
|
+
|
|
481
|
+
##### `customFilterOptions`
|
|
482
|
+
- **Type:** `{ value: string; label: string }[]`
|
|
483
|
+
- **Default:** `undefined`
|
|
484
|
+
- **Description:** Options for a dropdown filter (when filterType is 'custom').
|
|
485
|
+
- **Example:**
|
|
486
|
+
```typescript
|
|
487
|
+
customFilterOptions: [
|
|
488
|
+
{ value: 'active', label: 'Active' },
|
|
489
|
+
{ value: 'inactive', label: 'Inactive' }
|
|
490
|
+
]
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Display Customization
|
|
494
|
+
|
|
495
|
+
##### `customTemplate`
|
|
496
|
+
- **Type:** `TemplateRef<any>`
|
|
497
|
+
- **Default:** `undefined`
|
|
498
|
+
- **Description:** Custom template for rendering cell content (use with `type: 'custom-template'`).
|
|
499
|
+
- **Example:**
|
|
500
|
+
```html
|
|
501
|
+
<ng-template #statusTemplate let-row="row">
|
|
502
|
+
<span [class]="'status-' + row.status">{{ row.status }}</span>
|
|
503
|
+
</ng-template>
|
|
504
|
+
|
|
505
|
+
{
|
|
506
|
+
field: 'status',
|
|
507
|
+
header: 'Status',
|
|
508
|
+
type: 'custom-template',
|
|
509
|
+
customTemplate: statusTemplate
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
##### `customValueDisplay`
|
|
514
|
+
- **Type:** `(row: any) => string`
|
|
515
|
+
- **Default:** `undefined`
|
|
516
|
+
- **Description:** Function to transform the cell value for display.
|
|
517
|
+
- **Example:**
|
|
518
|
+
```typescript
|
|
519
|
+
{
|
|
520
|
+
field: 'price',
|
|
521
|
+
header: 'Price',
|
|
522
|
+
customValueDisplay: (row) => `$${row.price.toFixed(2)}`
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
##### `translateValue`
|
|
527
|
+
- **Type:** `{ [value: string]: string }`
|
|
528
|
+
- **Default:** `undefined`
|
|
529
|
+
- **Description:** Map of values to translated/display values.
|
|
530
|
+
- **Example:**
|
|
531
|
+
```typescript
|
|
532
|
+
{
|
|
533
|
+
field: 'status',
|
|
534
|
+
header: 'Status',
|
|
535
|
+
translateValue: {
|
|
536
|
+
'A': 'Active',
|
|
537
|
+
'I': 'Inactive',
|
|
538
|
+
'P': 'Pending'
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
#### Row Editing Configuration
|
|
544
|
+
|
|
545
|
+
##### `allowEditColumn`
|
|
546
|
+
- **Type:** `boolean`
|
|
547
|
+
- **Default:** `false`
|
|
548
|
+
- **Description:** Makes this column editable when row is in edit mode.
|
|
549
|
+
- **Example:** `allowEditColumn: true`
|
|
550
|
+
|
|
551
|
+
##### `rowEditType`
|
|
552
|
+
- **Type:** `StMaterialRowEditType`
|
|
553
|
+
- **Options:** `'string'` | `'number'` | `'boolean'` | `'date'` | `'custom'` | `'custom-dynamic-select'`
|
|
554
|
+
- **Default:** Auto-detected from `type`
|
|
555
|
+
- **Description:** Type of input to show when editing this column.
|
|
556
|
+
- **Example:** `rowEditType: 'number'`
|
|
557
|
+
|
|
558
|
+
##### `customRowEditOptions`
|
|
559
|
+
- **Type:** `{ value: any; label: string }[]`
|
|
560
|
+
- **Default:** `undefined`
|
|
561
|
+
- **Description:** Static options for a dropdown editor (when rowEditType is 'custom').
|
|
562
|
+
- **Example:**
|
|
563
|
+
```typescript
|
|
564
|
+
customRowEditOptions: [
|
|
565
|
+
{ value: 'admin', label: 'Administrator' },
|
|
566
|
+
{ value: 'user', label: 'Regular User' },
|
|
567
|
+
{ value: 'guest', label: 'Guest' }
|
|
568
|
+
]
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
##### `dynamicRowEditOptions`
|
|
572
|
+
- **Type:** `(row: any) => { value: any; label: string }[]`
|
|
573
|
+
- **Default:** `undefined`
|
|
574
|
+
- **Description:** Dynamic function to generate dropdown options based on the current row (when rowEditType is 'custom-dynamic-select').
|
|
575
|
+
- **Use case:** When options depend on other field values in the row.
|
|
576
|
+
- **Example:**
|
|
577
|
+
```typescript
|
|
578
|
+
dynamicRowEditOptions: (row) => {
|
|
579
|
+
if (row.country === 'USA') {
|
|
580
|
+
return [
|
|
581
|
+
{ value: 'NY', label: 'New York' },
|
|
582
|
+
{ value: 'CA', label: 'California' }
|
|
583
|
+
];
|
|
584
|
+
} else {
|
|
585
|
+
return [
|
|
586
|
+
{ value: 'LON', label: 'London' },
|
|
587
|
+
{ value: 'MAN', label: 'Manchester' }
|
|
588
|
+
];
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
##### `editColumnRequired`
|
|
594
|
+
- **Type:** `boolean`
|
|
595
|
+
- **Default:** `false`
|
|
596
|
+
- **Description:** Makes this column required when editing. Shows error if empty on save.
|
|
597
|
+
- **Example:** `editColumnRequired: true`
|
|
598
|
+
|
|
599
|
+
##### `disableEdit`
|
|
600
|
+
- **Type:** `(row: any) => boolean`
|
|
601
|
+
- **Default:** `undefined`
|
|
602
|
+
- **Description:** Function to determine if this specific column should be disabled for editing in a particular row.
|
|
603
|
+
- **Example:**
|
|
604
|
+
```typescript
|
|
605
|
+
disableEdit: (row) => row.status === 'locked'
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
##### `customEditRowValidator`
|
|
609
|
+
- **Type:** `(oldValue: any, newValue: any, row: any) => { isValid: boolean; errorMessage: string }`
|
|
610
|
+
- **Default:** `undefined`
|
|
611
|
+
- **Description:** Custom validation function for this column during editing.
|
|
612
|
+
- **Example:**
|
|
613
|
+
```typescript
|
|
614
|
+
customEditRowValidator: (oldValue, newValue, row) => {
|
|
615
|
+
if (newValue < 0) {
|
|
616
|
+
return { isValid: false, errorMessage: 'Value cannot be negative' };
|
|
617
|
+
}
|
|
618
|
+
if (newValue > row.maxValue) {
|
|
619
|
+
return { isValid: false, errorMessage: 'Value exceeds maximum' };
|
|
620
|
+
}
|
|
621
|
+
return { isValid: true, errorMessage: '' };
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
#### Actions Column Configuration
|
|
626
|
+
|
|
627
|
+
##### `actions`
|
|
628
|
+
- **Type:** `StMaterialTableActionColumnModel[]`
|
|
629
|
+
- **Default:** `undefined`
|
|
630
|
+
- **Description:** Array of action buttons to show in this column (use with `type: 'actions'`).
|
|
631
|
+
- **Example:**
|
|
632
|
+
```typescript
|
|
633
|
+
{
|
|
634
|
+
field: 'actions',
|
|
635
|
+
header: 'Actions',
|
|
636
|
+
type: 'actions',
|
|
637
|
+
sort: false,
|
|
638
|
+
filter: false,
|
|
639
|
+
actions: [
|
|
640
|
+
{
|
|
641
|
+
iconName: 'edit',
|
|
642
|
+
tooltipName: 'Edit User',
|
|
643
|
+
iconColor: 'primary',
|
|
644
|
+
action: (row) => this.editUser(row),
|
|
645
|
+
show: (row) => row.canEdit
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
iconName: 'delete',
|
|
649
|
+
tooltipName: 'Delete User',
|
|
650
|
+
iconColor: 'warn',
|
|
651
|
+
action: (row) => this.deleteUser(row),
|
|
652
|
+
show: (row) => row.canDelete
|
|
57
653
|
}
|
|
654
|
+
]
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
##### `actionsInMenu`
|
|
659
|
+
- **Type:** `boolean`
|
|
660
|
+
- **Default:** `false`
|
|
661
|
+
- **Description:** Shows actions in a dropdown menu instead of as individual buttons.
|
|
662
|
+
- **Example:** `actionsInMenu: true`
|
|
663
|
+
|
|
664
|
+
#### Action Button Model
|
|
665
|
+
|
|
666
|
+
Each action in the `actions` array has the following properties:
|
|
667
|
+
|
|
668
|
+
- **`iconName`** (string, required): Material icon name
|
|
669
|
+
- **`tooltipName`** (string, optional): Tooltip text
|
|
670
|
+
- **`iconColor`** ('primary' | 'warn' | 'accent', optional): Icon color
|
|
671
|
+
- **`action`** ((row: any, index?: number) => void, optional): Function called when clicked
|
|
672
|
+
- **`show`** ((row: any) => boolean, optional): Function to conditionally show/hide the action
|
|
673
|
+
- **`url`** (string[], optional): Router navigation path (alternative to `action`)
|
|
674
|
+
|
|
675
|
+
#### Other Properties
|
|
676
|
+
|
|
677
|
+
##### `notShowInColumnPick`
|
|
678
|
+
- **Type:** `boolean`
|
|
679
|
+
- **Default:** `false`
|
|
680
|
+
- **Description:** Hides this column from the column picker dialog.
|
|
681
|
+
- **Example:** `notShowInColumnPick: true`
|
|
682
|
+
|
|
683
|
+
##### `selectColumnLabel`
|
|
684
|
+
- **Type:** `string`
|
|
685
|
+
- **Default:** `undefined`
|
|
686
|
+
- **Description:** Used for special columns like selection, editing, extending. Sets the aria-label.
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## Outputs (Events)
|
|
691
|
+
|
|
692
|
+
### `loadData`
|
|
693
|
+
- **Type:** `StMaterialTableLoadData`
|
|
694
|
+
- **When emitted:** When lazy loading is enabled and data needs to be loaded (pagination, sorting, filtering changes).
|
|
695
|
+
- **Payload:**
|
|
696
|
+
```typescript
|
|
697
|
+
{
|
|
698
|
+
first: number; // Starting index
|
|
699
|
+
rows: number; // Number of rows to load
|
|
700
|
+
globalFilter: string; // Global search text
|
|
701
|
+
globalFilterColumns: string[]; // Columns to search
|
|
702
|
+
sortField: string; // Field to sort by
|
|
703
|
+
sortOrder: SortDirection; // 'asc' | 'desc'
|
|
704
|
+
filters: { [key: string]: StMaterialTableFilter }; // Column filters
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
- **Example:**
|
|
708
|
+
```typescript
|
|
709
|
+
(loadData)="onLoadData($event)"
|
|
710
|
+
|
|
711
|
+
onLoadData(event: StMaterialTableLoadData): void {
|
|
712
|
+
this.loading = true;
|
|
713
|
+
this.userService.getUsers(event).subscribe(response => {
|
|
714
|
+
this.users = response.data;
|
|
715
|
+
this.totalRecords = response.total;
|
|
716
|
+
this.loading = false;
|
|
58
717
|
});
|
|
59
718
|
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### `saveEditedRow`
|
|
722
|
+
- **Type:** `{ row: any; index: number }`
|
|
723
|
+
- **When emitted:** When user saves an edited existing row.
|
|
724
|
+
- **Payload:** The modified row object and its index.
|
|
725
|
+
- **Example:**
|
|
726
|
+
```typescript
|
|
727
|
+
(saveEditedRow)="onRowEdited($event)"
|
|
728
|
+
|
|
729
|
+
onRowEdited(event: { row: any; index: number }): void {
|
|
730
|
+
this.userService.updateUser(event.row).subscribe(
|
|
731
|
+
() => {
|
|
732
|
+
// Update your data array
|
|
733
|
+
this.users[event.index] = event.row;
|
|
734
|
+
this.snackbar.success('User updated successfully');
|
|
735
|
+
},
|
|
736
|
+
error => {
|
|
737
|
+
this.snackbar.error('Failed to update user');
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### `saveCreatedRow`
|
|
744
|
+
- **Type:** `any`
|
|
745
|
+
- **When emitted:** When user saves a newly created row (via `allowCreateRow`).
|
|
746
|
+
- **Payload:** The new row object.
|
|
747
|
+
- **Example:**
|
|
748
|
+
```typescript
|
|
749
|
+
(saveCreatedRow)="onRowCreated($event)"
|
|
750
|
+
|
|
751
|
+
onRowCreated(row: any): void {
|
|
752
|
+
this.userService.createUser(row).subscribe(
|
|
753
|
+
(createdUser) => {
|
|
754
|
+
// Add to your data array
|
|
755
|
+
this.users = [...this.users, createdUser];
|
|
756
|
+
this.snackbar.success('User created successfully');
|
|
757
|
+
},
|
|
758
|
+
error => {
|
|
759
|
+
this.snackbar.error('Failed to create user');
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
### `rowDeleted`
|
|
766
|
+
- **Type:** `{ row: any; index: number }`
|
|
767
|
+
- **When emitted:** When user deletes a row.
|
|
768
|
+
- **Payload:** The deleted row object and its index.
|
|
769
|
+
- **Example:**
|
|
770
|
+
```typescript
|
|
771
|
+
(rowDeleted)="onRowDeleted($event)"
|
|
772
|
+
|
|
773
|
+
onRowDeleted(event: { row: any; index: number }): void {
|
|
774
|
+
this.userService.deleteUser(event.row.id).subscribe(
|
|
775
|
+
() => {
|
|
776
|
+
// Remove from your data array
|
|
777
|
+
this.users = this.users.filter(u => u.id !== event.row.id);
|
|
778
|
+
this.snackbar.success('User deleted successfully');
|
|
779
|
+
},
|
|
780
|
+
error => {
|
|
781
|
+
this.snackbar.error('Failed to delete user');
|
|
782
|
+
}
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### `selectRowChange`
|
|
788
|
+
- **Type:** `any[]`
|
|
789
|
+
- **When emitted:** When row selection changes.
|
|
790
|
+
- **Payload:** Array of selected row objects.
|
|
791
|
+
- **Example:**
|
|
792
|
+
```typescript
|
|
793
|
+
(selectRowChange)="onSelectionChange($event)"
|
|
794
|
+
|
|
795
|
+
onSelectionChange(selectedRows: any[]): void {
|
|
796
|
+
this.selectedUsers = selectedRows;
|
|
797
|
+
console.log(`${selectedRows.length} users selected`);
|
|
798
|
+
}
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### `fieldValueChanged`
|
|
802
|
+
- **Type:** `{ row: any; field: string; value: any; index: number }`
|
|
803
|
+
- **When emitted:** When `autoSaveOnChange` is enabled and a field value changes.
|
|
804
|
+
- **Payload:** The row, field name, new value, and row index.
|
|
805
|
+
- **Important:** You must update your data source immediately when receiving this event.
|
|
806
|
+
- **Example:**
|
|
807
|
+
```typescript
|
|
808
|
+
(fieldValueChanged)="onFieldChanged($event)"
|
|
809
|
+
|
|
810
|
+
onFieldChanged(event: { row: any; field: string; value: any; index: number }): void {
|
|
811
|
+
// Update local data
|
|
812
|
+
this.users[event.index][event.field] = event.value;
|
|
813
|
+
|
|
814
|
+
// Optionally persist to server
|
|
815
|
+
this.userService.updateUser(event.row).subscribe();
|
|
816
|
+
}
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## Usage Examples
|
|
822
|
+
|
|
823
|
+
### Example 1: Basic Table with Sorting and Filtering
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
// Component
|
|
827
|
+
columns: StMaterialTableColumnModel[] = [
|
|
828
|
+
{ field: 'id', header: 'ID', width: '80px' },
|
|
829
|
+
{ field: 'firstName', header: 'First Name', filter: true },
|
|
830
|
+
{ field: 'lastName', header: 'Last Name', filter: true },
|
|
831
|
+
{ field: 'email', header: 'Email', filter: true },
|
|
832
|
+
{ field: 'age', header: 'Age', type: 'number' }
|
|
833
|
+
];
|
|
834
|
+
|
|
835
|
+
users: any[] = [
|
|
836
|
+
{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john@example.com', age: 30 },
|
|
837
|
+
{ id: 2, firstName: 'Jane', lastName: 'Smith', email: 'jane@example.com', age: 25 }
|
|
838
|
+
];
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
```html
|
|
842
|
+
<!-- Template -->
|
|
843
|
+
<ngx-st-material-table
|
|
844
|
+
tableTitle="Users"
|
|
845
|
+
[pageSize]="10"
|
|
846
|
+
[data]="users"
|
|
847
|
+
[initColumns]="columns"
|
|
848
|
+
[showGlobalSearch]="true"
|
|
849
|
+
[allowPickColumns]="true"
|
|
850
|
+
localStorageName="users-table">
|
|
851
|
+
</ngx-st-material-table>
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Example 2: Lazy Loading Table
|
|
855
|
+
|
|
856
|
+
```typescript
|
|
857
|
+
// Component
|
|
858
|
+
columns: StMaterialTableColumnModel[] = [
|
|
859
|
+
{ field: 'name', header: 'Name', filter: true },
|
|
860
|
+
{ field: 'status', header: 'Status', filter: true, filterType: 'custom',
|
|
861
|
+
customFilterOptions: [
|
|
862
|
+
{ value: 'active', label: 'Active' },
|
|
863
|
+
{ value: 'inactive', label: 'Inactive' }
|
|
864
|
+
]
|
|
865
|
+
}
|
|
866
|
+
];
|
|
867
|
+
|
|
868
|
+
users: any[] = [];
|
|
869
|
+
totalRecords = 0;
|
|
870
|
+
loading = false;
|
|
871
|
+
|
|
872
|
+
onLoadData(event: StMaterialTableLoadData): void {
|
|
873
|
+
this.loading = true;
|
|
874
|
+
this.userService.getUsers(event).subscribe(response => {
|
|
875
|
+
this.users = response.data;
|
|
876
|
+
this.totalRecords = response.total;
|
|
877
|
+
this.loading = false;
|
|
878
|
+
});
|
|
60
879
|
}
|
|
61
880
|
```
|
|
62
881
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
882
|
+
```html
|
|
883
|
+
<!-- Template -->
|
|
884
|
+
<ngx-st-material-table
|
|
885
|
+
[lazyLoading]="true"
|
|
886
|
+
[isLoading]="loading"
|
|
887
|
+
[dataLength]="totalRecords"
|
|
888
|
+
[data]="users"
|
|
889
|
+
[initColumns]="columns"
|
|
890
|
+
(loadData)="onLoadData($event)">
|
|
891
|
+
</ngx-st-material-table>
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
### Example 3: Editable Table with Validation
|
|
895
|
+
|
|
896
|
+
```typescript
|
|
897
|
+
// Component
|
|
898
|
+
columns: StMaterialTableColumnModel[] = [
|
|
899
|
+
{
|
|
900
|
+
field: 'name',
|
|
901
|
+
header: 'Name',
|
|
902
|
+
allowEditColumn: true,
|
|
903
|
+
editColumnRequired: true
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
field: 'quantity',
|
|
907
|
+
header: 'Quantity',
|
|
908
|
+
type: 'number',
|
|
909
|
+
allowEditColumn: true,
|
|
910
|
+
rowEditType: 'number',
|
|
911
|
+
editColumnRequired: true,
|
|
912
|
+
customEditRowValidator: (oldValue, newValue, row) => {
|
|
913
|
+
if (newValue < 0) {
|
|
914
|
+
return { isValid: false, errorMessage: 'Quantity cannot be negative' };
|
|
915
|
+
}
|
|
916
|
+
if (newValue > 100) {
|
|
917
|
+
return { isValid: false, errorMessage: 'Quantity cannot exceed 100' };
|
|
918
|
+
}
|
|
919
|
+
return { isValid: true, errorMessage: '' };
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
field: 'status',
|
|
924
|
+
header: 'Status',
|
|
925
|
+
allowEditColumn: true,
|
|
926
|
+
rowEditType: 'custom',
|
|
927
|
+
customRowEditOptions: [
|
|
928
|
+
{ value: 'draft', label: 'Draft' },
|
|
929
|
+
{ value: 'published', label: 'Published' }
|
|
930
|
+
]
|
|
931
|
+
}
|
|
932
|
+
];
|
|
933
|
+
|
|
934
|
+
onRowEdited(event: { row: any; index: number }): void {
|
|
935
|
+
this.updateItem(event.row);
|
|
936
|
+
}
|
|
68
937
|
|
|
69
|
-
|
|
938
|
+
canEditItem(row: any): boolean {
|
|
939
|
+
return row.status !== 'archived';
|
|
940
|
+
}
|
|
941
|
+
```
|
|
70
942
|
|
|
71
|
-
|
|
943
|
+
```html
|
|
944
|
+
<!-- Template -->
|
|
945
|
+
<ngx-st-material-table
|
|
946
|
+
[data]="items"
|
|
947
|
+
[initColumns]="columns"
|
|
948
|
+
[allowEditRow]="true"
|
|
949
|
+
[allowCreateRow]="true"
|
|
950
|
+
[canEditRowValidator]="canEditItem"
|
|
951
|
+
(saveEditedRow)="onRowEdited($event)"
|
|
952
|
+
(saveCreatedRow)="onRowCreated($event)"
|
|
953
|
+
(rowDeleted)="onRowDeleted($event)">
|
|
954
|
+
</ngx-st-material-table>
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
### Example 4: Auto-Save Table (Instant Updates)
|
|
72
958
|
|
|
73
959
|
```typescript
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
960
|
+
// Component
|
|
961
|
+
columns: StMaterialTableColumnModel[] = [
|
|
962
|
+
{ field: 'product', header: 'Product' },
|
|
963
|
+
{
|
|
964
|
+
field: 'quantity',
|
|
965
|
+
header: 'Quantity',
|
|
966
|
+
type: 'number',
|
|
967
|
+
allowEditColumn: true,
|
|
968
|
+
rowEditType: 'number'
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
field: 'active',
|
|
972
|
+
header: 'Active',
|
|
973
|
+
type: 'boolean',
|
|
974
|
+
allowEditColumn: true
|
|
975
|
+
}
|
|
976
|
+
];
|
|
977
|
+
|
|
978
|
+
onFieldChanged(event: { row: any; field: string; value: any; index: number }): void {
|
|
979
|
+
// Update local data immediately
|
|
980
|
+
this.items[event.index][event.field] = event.value;
|
|
94
981
|
|
|
95
|
-
|
|
96
|
-
|
|
982
|
+
// Persist to server
|
|
983
|
+
this.itemService.updateItem(event.row).subscribe();
|
|
984
|
+
}
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
```html
|
|
988
|
+
<!-- Template -->
|
|
989
|
+
<ngx-st-material-table
|
|
990
|
+
[data]="items"
|
|
991
|
+
[initColumns]="columns"
|
|
992
|
+
[allowEditRow]="true"
|
|
993
|
+
[autoSaveOnChange]="true"
|
|
994
|
+
[setNewDataWithoutRefresh]="true"
|
|
995
|
+
(fieldValueChanged)="onFieldChanged($event)">
|
|
996
|
+
</ngx-st-material-table>
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
### Example 5: Selection Table
|
|
1000
|
+
|
|
1001
|
+
```typescript
|
|
1002
|
+
// Component
|
|
1003
|
+
columns: StMaterialTableColumnModel[] = [
|
|
1004
|
+
{ field: 'id', header: 'ID' },
|
|
1005
|
+
{ field: 'name', header: 'Name' },
|
|
1006
|
+
{ field: 'email', header: 'Email' }
|
|
1007
|
+
];
|
|
1008
|
+
|
|
1009
|
+
selectedUsers: any[] = [];
|
|
1010
|
+
|
|
1011
|
+
onSelectionChange(selected: any[]): void {
|
|
1012
|
+
this.selectedUsers = selected;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
formatSelectedUser(row: any): string {
|
|
1016
|
+
return `${row.name} (${row.email})`;
|
|
1017
|
+
}
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
```html
|
|
1021
|
+
<!-- Template -->
|
|
1022
|
+
<ngx-st-material-table
|
|
1023
|
+
[data]="users"
|
|
1024
|
+
[initColumns]="columns"
|
|
1025
|
+
[allowSelectRow]="true"
|
|
1026
|
+
selectionFieldLabel="name"
|
|
1027
|
+
[selectRowValueDisplay]="formatSelectedUser"
|
|
1028
|
+
(selectRowChange)="onSelectionChange($event)">
|
|
1029
|
+
</ngx-st-material-table>
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
### Example 6: Expandable Rows
|
|
1033
|
+
|
|
1034
|
+
```html
|
|
1035
|
+
<!-- Template -->
|
|
1036
|
+
<ng-template #detailTemplate let-data="data">
|
|
1037
|
+
<div class="row-detail">
|
|
1038
|
+
<h4>Additional Details</h4>
|
|
1039
|
+
<p><strong>Address:</strong> {{ data.address }}</p>
|
|
1040
|
+
<p><strong>Phone:</strong> {{ data.phone }}</p>
|
|
1041
|
+
<p><strong>Notes:</strong> {{ data.notes }}</p>
|
|
1042
|
+
</div>
|
|
1043
|
+
</ng-template>
|
|
1044
|
+
|
|
1045
|
+
<ngx-st-material-table
|
|
1046
|
+
[data]="users"
|
|
1047
|
+
[initColumns]="columns"
|
|
1048
|
+
[allowExtendRow]="true"
|
|
1049
|
+
[extendedRowTemplate]="detailTemplate">
|
|
1050
|
+
</ngx-st-material-table>
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
### Example 7: Custom Column Template
|
|
1054
|
+
|
|
1055
|
+
```html
|
|
1056
|
+
<!-- Template -->
|
|
1057
|
+
<ng-template #statusBadgeTemplate let-row="row">
|
|
1058
|
+
<span class="badge" [ngClass]="{
|
|
1059
|
+
'badge-success': row.status === 'active',
|
|
1060
|
+
'badge-danger': row.status === 'inactive',
|
|
1061
|
+
'badge-warning': row.status === 'pending'
|
|
1062
|
+
}">
|
|
1063
|
+
{{ row.status | uppercase }}
|
|
1064
|
+
</span>
|
|
1065
|
+
</ng-template>
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
```typescript
|
|
1069
|
+
// Component
|
|
1070
|
+
@ViewChild('statusBadgeTemplate') statusBadgeTemplate!: TemplateRef<any>;
|
|
1071
|
+
|
|
1072
|
+
ngAfterViewInit() {
|
|
1073
|
+
this.columns = [
|
|
1074
|
+
{ field: 'name', header: 'Name' },
|
|
97
1075
|
{
|
|
98
|
-
field: '
|
|
99
|
-
header: '
|
|
100
|
-
type: '
|
|
101
|
-
|
|
102
|
-
}
|
|
1076
|
+
field: 'status',
|
|
1077
|
+
header: 'Status',
|
|
1078
|
+
type: 'custom-template',
|
|
1079
|
+
customTemplate: this.statusBadgeTemplate
|
|
1080
|
+
}
|
|
103
1081
|
];
|
|
1082
|
+
}
|
|
1083
|
+
```
|
|
104
1084
|
|
|
105
|
-
|
|
106
|
-
onFieldValueChanged(event: { row: any; field: string; value: any }) {
|
|
107
|
-
const index = this.tableData.findIndex(r => r.id === event.row.id);
|
|
108
|
-
if (index !== -1) {
|
|
109
|
-
this.tableData[index][event.field] = event.value;
|
|
110
|
-
|
|
111
|
-
// Optional: Send to API immediately or batch updates
|
|
112
|
-
console.log('Updated:', event.row.name, event.field, event.value);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
1085
|
+
### Example 8: Actions Column
|
|
115
1086
|
|
|
116
|
-
|
|
117
|
-
|
|
1087
|
+
```typescript
|
|
1088
|
+
// Component
|
|
1089
|
+
columns: StMaterialTableColumnModel[] = [
|
|
1090
|
+
{ field: 'name', header: 'Name' },
|
|
1091
|
+
{ field: 'email', header: 'Email' },
|
|
1092
|
+
{
|
|
1093
|
+
field: 'actions',
|
|
1094
|
+
header: 'Actions',
|
|
1095
|
+
type: 'actions',
|
|
1096
|
+
sort: false,
|
|
1097
|
+
filter: false,
|
|
1098
|
+
width: '120px',
|
|
1099
|
+
actions: [
|
|
1100
|
+
{
|
|
1101
|
+
iconName: 'visibility',
|
|
1102
|
+
tooltipName: 'View Details',
|
|
1103
|
+
action: (row) => this.viewUser(row)
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
iconName: 'edit',
|
|
1107
|
+
tooltipName: 'Edit User',
|
|
1108
|
+
iconColor: 'primary',
|
|
1109
|
+
action: (row) => this.editUser(row),
|
|
1110
|
+
show: (row) => row.canEdit
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
iconName: 'delete',
|
|
1114
|
+
tooltipName: 'Delete User',
|
|
1115
|
+
iconColor: 'warn',
|
|
1116
|
+
action: (row, index) => this.deleteUser(row, index),
|
|
1117
|
+
show: (row) => row.canDelete
|
|
1118
|
+
}
|
|
1119
|
+
]
|
|
118
1120
|
}
|
|
1121
|
+
];
|
|
1122
|
+
|
|
1123
|
+
viewUser(row: any): void {
|
|
1124
|
+
this.router.navigate(['/users', row.id]);
|
|
119
1125
|
}
|
|
1126
|
+
|
|
1127
|
+
editUser(row: any): void {
|
|
1128
|
+
// Open edit dialog
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
deleteUser(row: any, index: number): void {
|
|
1132
|
+
// Delete logic
|
|
1133
|
+
}
|
|
1134
|
+
```
|
|
1135
|
+
|
|
1136
|
+
### Example 9: Dynamic Select Options Based on Row
|
|
1137
|
+
|
|
1138
|
+
```typescript
|
|
1139
|
+
// Component
|
|
1140
|
+
columns: StMaterialTableColumnModel[] = [
|
|
1141
|
+
{ field: 'country', header: 'Country', allowEditColumn: true },
|
|
1142
|
+
{
|
|
1143
|
+
field: 'state',
|
|
1144
|
+
header: 'State',
|
|
1145
|
+
allowEditColumn: true,
|
|
1146
|
+
rowEditType: 'custom-dynamic-select',
|
|
1147
|
+
dynamicRowEditOptions: (row) => {
|
|
1148
|
+
if (row.country === 'USA') {
|
|
1149
|
+
return [
|
|
1150
|
+
{ value: 'NY', label: 'New York' },
|
|
1151
|
+
{ value: 'CA', label: 'California' },
|
|
1152
|
+
{ value: 'TX', label: 'Texas' }
|
|
1153
|
+
];
|
|
1154
|
+
} else if (row.country === 'UK') {
|
|
1155
|
+
return [
|
|
1156
|
+
{ value: 'ENG', label: 'England' },
|
|
1157
|
+
{ value: 'SCT', label: 'Scotland' },
|
|
1158
|
+
{ value: 'WLS', label: 'Wales' }
|
|
1159
|
+
];
|
|
1160
|
+
}
|
|
1161
|
+
return [];
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
];
|
|
120
1165
|
```
|
|
121
1166
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
1167
|
+
---
|
|
1168
|
+
|
|
1169
|
+
## Best Practices
|
|
1170
|
+
|
|
1171
|
+
1. **Use `localStorageName`** to persist user preferences (column order, filters, sorting)
|
|
1172
|
+
|
|
1173
|
+
2. **Enable `lazyLoading`** for large datasets (1000+ records)
|
|
1174
|
+
|
|
1175
|
+
3. **Use `autoSaveOnChange`** for simple quantity/selection tables where immediate updates are desired
|
|
1176
|
+
|
|
1177
|
+
4. **Use `setNewDataWithoutRefresh`** when frequently updating data to prevent UI flickering
|
|
1178
|
+
|
|
1179
|
+
5. **Provide validators** (`canEditRowValidator`, `customEditRowValidator`) to enforce business rules
|
|
1180
|
+
|
|
1181
|
+
6. **Use custom templates** for complex cell rendering instead of trying to format with `customValueDisplay`
|
|
1182
|
+
|
|
1183
|
+
7. **Set appropriate column widths** to prevent layout shifts
|
|
1184
|
+
|
|
1185
|
+
8. **Use `notShowInColumnPick`** for action columns or columns that should always be visible
|
|
1186
|
+
|
|
1187
|
+
9. **Implement proper error handling** in your event handlers (saveEditedRow, rowDeleted, etc.)
|
|
1188
|
+
|
|
1189
|
+
10. **Use `selectRowValueDisplay`** when simple field labels aren't enough for selected row display
|
|
1190
|
+
|
|
1191
|
+
---
|
|
1192
|
+
|
|
1193
|
+
## Common Patterns
|
|
1194
|
+
|
|
1195
|
+
### Pattern 1: Master-Detail Table
|
|
1196
|
+
Use `allowExtendRow` with `extendedRowTemplate` to show additional details without navigation.
|
|
1197
|
+
|
|
1198
|
+
### Pattern 2: Quick Edit Grid
|
|
1199
|
+
Use `autoSaveOnChange` with `setNewDataWithoutRefresh` for spreadsheet-like editing.
|
|
1200
|
+
|
|
1201
|
+
### Pattern 3: Selection List
|
|
1202
|
+
Use `allowSelectRow` with `selectRowOnlyOne` for choosing a single item (like a lookup).
|
|
1203
|
+
|
|
1204
|
+
### Pattern 4: CRUD Table
|
|
1205
|
+
Combine `allowEditRow`, `allowCreateRow`, and action handlers for full CRUD operations.
|
|
127
1206
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- ✅ Immediate feedback
|
|
131
|
-
- ✅ Works perfectly with row selection
|
|
132
|
-
- ✅ Parent receives updates in real-time
|
|
1207
|
+
### Pattern 5: Filtered Report
|
|
1208
|
+
Use `showGlobalSearch`, column filters, and `localStorageName` for a searchable report with saved preferences.
|
|
133
1209
|
|
|
134
|
-
|
|
1210
|
+
---
|
|
135
1211
|
|
|
136
|
-
|
|
137
|
-
> Note: Don't forget to add `--project ngx-st-tables` or else it will be added to the default project in your `angular.json` file.
|
|
1212
|
+
## Troubleshooting
|
|
138
1213
|
|
|
139
|
-
|
|
1214
|
+
### Table doesn't update when data changes
|
|
1215
|
+
- Ensure you're passing a new array reference: `this.data = [...updatedData]`
|
|
1216
|
+
- Or use `setNewDataWithoutRefresh` if you want in-place updates
|
|
140
1217
|
|
|
141
|
-
|
|
1218
|
+
### Focus lost during editing
|
|
1219
|
+
- Enable `setNewDataWithoutRefresh` for frequent updates
|
|
1220
|
+
- Ensure data array length doesn't change during edits
|
|
142
1221
|
|
|
143
|
-
|
|
1222
|
+
### Filters not working
|
|
1223
|
+
- Check that columns have `filter: true`
|
|
1224
|
+
- Verify `filterType` is set correctly
|
|
1225
|
+
- For custom filters, provide `customFilterOptions`
|
|
144
1226
|
|
|
145
|
-
|
|
1227
|
+
### Lazy loading not triggered
|
|
1228
|
+
- Ensure `lazyLoading` is true
|
|
1229
|
+
- Check that `loadData` event handler is connected
|
|
1230
|
+
- Verify you're setting `dataLength` with total record count
|
|
146
1231
|
|
|
147
|
-
|
|
1232
|
+
### Row editing disabled
|
|
1233
|
+
- Check `allowEditRow` is true
|
|
1234
|
+
- Verify columns have `allowEditColumn: true`
|
|
1235
|
+
- Check `canEditRowValidator` isn't returning false
|
|
148
1236
|
|
|
149
|
-
|
|
1237
|
+
---
|
|
150
1238
|
|
|
151
|
-
|
|
1239
|
+
This documentation covers all inputs, outputs, and configuration options for the Material Table component. For additional help, refer to the component source code or contact the development team.
|
|
152
1240
|
|
|
153
|
-
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|