@thkl/agrid 0.1.10 → 0.1.12
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 +155 -6
- package/fesm2022/thkl-agrid.mjs +3516 -715
- package/fesm2022/thkl-agrid.mjs.map +1 -1
- package/package.json +1 -1
- package/types/thkl-agrid.d.ts +1081 -70
- package/types/thkl-agrid.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -72,14 +72,69 @@ be dragged.
|
|
|
72
72
|
`confirmRowDelete` protects grid delete actions with a localized in-row Yes/No confirmation.
|
|
73
73
|
Direct calls to `AgridDataSource.removeRow()` remain immediate.
|
|
74
74
|
|
|
75
|
-
`enableRowMarking`
|
|
76
|
-
|
|
75
|
+
`enableRowMarking` makes each control-cell row header clickable and adds a checkbox. Clicking the
|
|
76
|
+
header outside its nested controls toggles the same mark state and emits `(rowMark)` with the row,
|
|
77
|
+
its original datasource index, and the resulting `marked` state. Marked rows are included in
|
|
78
|
+
keyboard, cell-context, and row-context copy operations. Read `grid.markedRowIndices()` or call
|
|
77
79
|
`grid.clearMarkedRows()` when the host needs to inspect or reset the copy basket.
|
|
78
80
|
|
|
79
81
|
Marking is independent from row selection. Cell and range copy use the same copied columns for
|
|
80
82
|
every marked row, while Copy row uses every visible column. Duplicate rows are omitted, and marked
|
|
81
83
|
rows remain included when filters hide them.
|
|
82
84
|
|
|
85
|
+
Selecting numeric cells displays a live status bar with count, sum, average, minimum, and maximum.
|
|
86
|
+
Read the same values from `grid.selectionSummary()`. The signal is `null` when the active selection
|
|
87
|
+
contains no finite numeric values.
|
|
88
|
+
|
|
89
|
+
Set `enableColumnMarking: true` to toggle complete-column highlighting by clicking a header outside
|
|
90
|
+
its menu and resize controls. The grid exposes `markedColumnFields()` and emits `(columnMark)`.
|
|
91
|
+
|
|
92
|
+
Append custom commands to one column's menu and handle them through one typed output:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
{ field: 'status', header: 'Status', headerMenuItems: [
|
|
96
|
+
{ key: 'archive', label: 'Archive', icon: '⌂' },
|
|
97
|
+
] }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```html
|
|
101
|
+
<agrid [provider]="provider" (columnHeaderAction)="onColumnHeaderAction($event)" />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The event contains `{ column, key }`.
|
|
105
|
+
|
|
106
|
+
Use `(firstDataRendered)` when host logic must wait until the grid has completed its first render
|
|
107
|
+
containing datasource rows:
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<agrid [provider]="provider" (firstDataRendered)="onGridReady($event)" />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The event fires once per grid component. An initially empty datasource delays it until rows arrive.
|
|
114
|
+
Server-side loading placeholders do not count as rendered data. The payload contains `rows`,
|
|
115
|
+
`rowCount`, `provider`, and `datasource`.
|
|
116
|
+
|
|
117
|
+
For commands that change `textAlign` at runtime, keep the writable signal in the host instead of
|
|
118
|
+
mutating `event.column`:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
readonly salaryAlignment = signal<'left' | 'center' | 'right'>('right');
|
|
122
|
+
|
|
123
|
+
// Column definition
|
|
124
|
+
{ field: 'salary', header: 'Salary', textAlign: this.salaryAlignment }
|
|
125
|
+
|
|
126
|
+
onColumnHeaderAction(event: ColumnHeaderActionEvent<Employee>): void {
|
|
127
|
+
if (event.column.field !== 'salary') return;
|
|
128
|
+
if (event.key === 'align-left') this.salaryAlignment.set('left');
|
|
129
|
+
if (event.key === 'align-center') this.salaryAlignment.set('center');
|
|
130
|
+
if (event.key === 'align-right') this.salaryAlignment.set('right');
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Assigning `event.column.textAlign = 'center'` mutates plain configuration and does not trigger an
|
|
135
|
+
Angular update. Calling `.set()` on `event.column.textAlign` is also not type-safe because the
|
|
136
|
+
property may contain a static string or a read-only signal.
|
|
137
|
+
|
|
83
138
|
## Menu bar
|
|
84
139
|
|
|
85
140
|
Set `menuBarItems` to render command buttons above the headers. An item with `items` becomes a
|
|
@@ -171,6 +226,10 @@ does not include. Numbers offer `=`, `≠`, `>`, `≥`, `<`, `≤`, and `between
|
|
|
171
226
|
before / after / between. Conditions combine with the header text filter, value picker, and other
|
|
172
227
|
columns using AND semantics, and are included in `AgridControl.toJSON()` state.
|
|
173
228
|
|
|
229
|
+
The header arrow opens the complete column menu. The condition button beside the inline filter
|
|
230
|
+
opens only the condition operator and operand controls; sorting, layout, grouping, custom commands,
|
|
231
|
+
clear-all actions, and distinct-value selection remain in the complete menu.
|
|
232
|
+
|
|
174
233
|
```ts
|
|
175
234
|
const columns: ColDef<Order>[] = [
|
|
176
235
|
{ field: 'reference', header: 'Reference', filterable: true },
|
|
@@ -237,7 +296,8 @@ refetch:
|
|
|
237
296
|
```
|
|
238
297
|
|
|
239
298
|
Text/range/quick events are debounced by `filterDebounceMs` (default 300 ms; `0` disables). The
|
|
240
|
-
|
|
299
|
+
The distinct-value picker is hidden in this mode unless the column supplies an explicit `values`
|
|
300
|
+
list representing the complete server-side value set.
|
|
241
301
|
|
|
242
302
|
## Grouping and aggregates
|
|
243
303
|
|
|
@@ -270,6 +330,7 @@ const treeConfig: AgridTreeConfig<OrgRow> = {
|
|
|
270
330
|
getId: row => row.id,
|
|
271
331
|
getParentId: row => row.parentId, // null / unknown id ⇒ root row
|
|
272
332
|
treeField: 'name', // column that shows the twisty
|
|
333
|
+
aggregateTreeNodes: true, // parent cells roll up descendant leaves
|
|
273
334
|
};
|
|
274
335
|
|
|
275
336
|
readonly provider = new AgridProvider<OrgRow>({
|
|
@@ -279,6 +340,11 @@ readonly provider = new AgridProvider<OrgRow>({
|
|
|
279
340
|
});
|
|
280
341
|
```
|
|
281
342
|
|
|
343
|
+
With `aggregateTreeNodes: true`, every expandable row displays descendant-leaf rollups in columns
|
|
344
|
+
that define `aggregate` (or have one set through `AgridControl`). For example,
|
|
345
|
+
`{ field: 'amount', aggregate: 'sum' }` shows the sum of a node's leaves in that node's amount cell.
|
|
346
|
+
Collapsed leaves still contribute. Filtering recalculates the rollups over the matching tree.
|
|
347
|
+
|
|
282
348
|
For path-like values such as `01.01.0001`, return the ordered segments:
|
|
283
349
|
|
|
284
350
|
```ts
|
|
@@ -309,10 +375,19 @@ tree.
|
|
|
309
375
|
Tree mode can be combined with `masterDetail: true` and a `detailRenderer`. Detail expanders are
|
|
310
376
|
shown only for leaf rows; parent rows retain their tree expand/collapse control.
|
|
311
377
|
|
|
378
|
+
Set `detailColumnField` to a column field when the panel should expose one larger multiline value.
|
|
379
|
+
The formatted value is shown normally; click it or focus it and press Enter to open a textarea.
|
|
380
|
+
Blur or Ctrl/Cmd+Enter commits, while Escape cancels. Editability, validation, history, and edit
|
|
381
|
+
events follow the linked column's normal cell behavior.
|
|
382
|
+
Set `detailActions` to add text-template buttons above the textarea. Each action has an `id`,
|
|
383
|
+
`label`, and optional `text` string or row-aware resolver; clicking inserts at the current
|
|
384
|
+
selection, or appends if the button opens the textarea.
|
|
385
|
+
|
|
312
386
|
## Standalone tree control
|
|
313
387
|
|
|
314
388
|
Use `<agrid-tree>` for the same parent-ID or path hierarchy without grid columns. It adds tree
|
|
315
|
-
keyboard navigation and optional single or multi-selection.
|
|
389
|
+
keyboard navigation and optional single or multi-selection. Since this component has no columns,
|
|
390
|
+
it ignores `aggregateTreeNodes`; descendant rollups apply only to tree mode in `<agrid>`.
|
|
316
391
|
|
|
317
392
|
```ts
|
|
318
393
|
readonly treeProvider = new AgridTreeProvider<OrgRow>({
|
|
@@ -342,6 +417,77 @@ The tree uses the shared `--agrid-color-text`, `--agrid-color-text-muted`,
|
|
|
342
417
|
`--agrid-color-accent`, `--agrid-color-accent-subtle`, `--agrid-color-accent-fg`,
|
|
343
418
|
`--agrid-color-border`, `--agrid-color-bg`, and `--agrid-color-bg-muted` CSS variables.
|
|
344
419
|
|
|
420
|
+
## Pivot tables
|
|
421
|
+
|
|
422
|
+
Use `pivotConfig` to derive a read-only client-side cross-tabulation from a flat datasource. The
|
|
423
|
+
first pivot release supports one row dimension, one column dimension, and one value field.
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
const provider = new AgridProvider<Sale>({
|
|
427
|
+
columns: [
|
|
428
|
+
{ field: 'region', header: 'Region' },
|
|
429
|
+
{ field: 'quarter', header: 'Quarter' },
|
|
430
|
+
{ field: 'revenue', header: 'Revenue', type: 'number', formatter: currency },
|
|
431
|
+
],
|
|
432
|
+
datasource: new AgridDataSource(sales),
|
|
433
|
+
pivotConfig: {
|
|
434
|
+
rowField: 'region',
|
|
435
|
+
columnField: 'quarter',
|
|
436
|
+
valueField: 'revenue',
|
|
437
|
+
aggregate: 'sum',
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Each distinct `rowField` value becomes one row and each distinct `columnField` value becomes a
|
|
443
|
+
generated column. Intersections use `sum` by default and also support `avg`, `min`, `max`, `count`,
|
|
444
|
+
or a custom `(values) => result` function. Dimension labels and pivot values reuse source column
|
|
445
|
+
formatters. Missing intersections render empty.
|
|
446
|
+
|
|
447
|
+
Pivot rows react to datasource replacement and updates. They are derived values, so editing,
|
|
448
|
+
adding, reordering, master/detail, tree mode, server-side row models, and aggregate footers are
|
|
449
|
+
disabled or rejected in pivot mode. Client-side filtering, sorting, selection, and pagination
|
|
450
|
+
continue through the normal grid pipeline. Multi-level dimensions and totals are intentionally
|
|
451
|
+
outside this first slice.
|
|
452
|
+
|
|
453
|
+
When `showSidebar` is enabled, pivot grids add a **Pivot** sidebar tab. It updates `rowField`,
|
|
454
|
+
`columnField`, `valueField`, and built-in aggregate functions immediately without replacing the
|
|
455
|
+
provider. Assigning `provider.pivotConfig` programmatically uses the same reactive path.
|
|
456
|
+
|
|
457
|
+
### Saving and restoring settings
|
|
458
|
+
|
|
459
|
+
`saveSettings()` returns a detached, versioned object containing the pivot configuration and the
|
|
460
|
+
existing control state (column visibility, width, order, pinning, filters, sorts, pagination, and
|
|
461
|
+
aggregates). It is safe to JSON-encode and send to a backend. `loadSettings()` applies it to an
|
|
462
|
+
already-rendered grid immediately.
|
|
463
|
+
|
|
464
|
+
```ts
|
|
465
|
+
const settings = provider.saveSettings();
|
|
466
|
+
await api.saveGridSettings(settings);
|
|
467
|
+
|
|
468
|
+
const restored = await api.loadGridSettings();
|
|
469
|
+
provider.loadSettings(restored);
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
The component exposes the same methods through `viewChild(AgridComponent)`. Sidebar pivot and
|
|
473
|
+
column-visibility changes emit the complete snapshot through `(settingsChange)`:
|
|
474
|
+
|
|
475
|
+
```html
|
|
476
|
+
<agrid #grid [provider]="provider" (settingsChange)="saveSettings($event)" />
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
saveSettings(settings: AgridSettings): void {
|
|
481
|
+
void api.saveGridSettings(settings);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Loading after the grid exists:
|
|
485
|
+
grid().loadSettings(savedSettings);
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Custom aggregate functions are executable code and cannot be represented in JSON; attempting to
|
|
489
|
+
save one throws an explicit error. Register custom functions in application code instead.
|
|
490
|
+
|
|
345
491
|
## Page selector
|
|
346
492
|
|
|
347
493
|
Use `<agrid-page-selector>` to navigate pages by previous/next button, dropdown, or typed ID.
|
|
@@ -374,7 +520,8 @@ Use `rowChanged` to send one request after the user edits one or more fields in
|
|
|
374
520
|
```ts
|
|
375
521
|
saveRow(event: RowUpdateEvent<Person>): void {
|
|
376
522
|
this.http.patch(`/api/people/${event.row.id}`, event.row).subscribe(() => {
|
|
377
|
-
this.
|
|
523
|
+
this.provider.control.indicate(event.originalIndex, '#2da44e', 1000);
|
|
524
|
+
this.provider.control.clearChangedCells(event.originalIndex);
|
|
378
525
|
});
|
|
379
526
|
}
|
|
380
527
|
```
|
|
@@ -382,6 +529,8 @@ saveRow(event: RowUpdateEvent<Person>): void {
|
|
|
382
529
|
The event fires with the latest complete row when inline navigation leaves that row, or when the
|
|
383
530
|
sidebar editor Save button is used. `cellEdit` and `recordEdit` remain available for every committed
|
|
384
531
|
field change. With `showChangedCellIndicator: true`, changed cells keep a corner marker until the
|
|
385
|
-
PATCH succeeds. Override `--agrid-color-cell-changed` to customize its color.
|
|
532
|
+
PATCH succeeds. Override `--agrid-color-cell-changed` to customize its color. Call
|
|
533
|
+
`control.indicate(index, color, durationMs)` to flash a complete row for transient server-side
|
|
534
|
+
feedback.
|
|
386
535
|
|
|
387
536
|
Full documentation and demos: https://thkl.github.io/agrid/
|