spiderly 19.9.2 → 19.9.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.
- package/agent/docs/angular-customization/index.md +10 -2
- package/agent/docs/backend-hooks/index.md +12 -1
- package/fesm2022/spiderly.mjs +243 -6
- package/fesm2022/spiderly.mjs.map +1 -1
- package/lib/components/spiderly-data-table/spiderly-data-table.component.d.ts +95 -3
- package/package.json +1 -1
- package/styles/components/spiderly-data-table/spiderly-data-table.component.scss +26 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AfterViewInit, EventEmitter, OnDestroy, OnInit, TemplateRef } from '@angular/core';
|
|
2
2
|
import { ActivatedRoute, Router } from '@angular/router';
|
|
3
3
|
import { TranslocoService } from '@jsverse/transloco';
|
|
4
|
-
import { SelectItem } from 'primeng/api';
|
|
4
|
+
import { SelectItem, SortMeta } from 'primeng/api';
|
|
5
5
|
import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog';
|
|
6
6
|
import { Table, TableFilterEvent, TableLazyLoadEvent } from 'primeng/table';
|
|
7
7
|
import { Observable } from 'rxjs';
|
|
@@ -78,6 +78,22 @@ export declare class SpiderlyDataTableComponent implements OnInit, AfterViewInit
|
|
|
78
78
|
stateKey?: string;
|
|
79
79
|
/** 'session' persists across refresh only; 'local' persists indefinitely. */
|
|
80
80
|
stateStorage: 'session' | 'local';
|
|
81
|
+
/**
|
|
82
|
+
* Column field the table sorts by while the user has no sort of their own — applied on
|
|
83
|
+
* first load (persisted state, when present, wins) and re-applied whenever an action
|
|
84
|
+
* would leave the table unsorted (tri-state header click, Clear filters). Shows as a
|
|
85
|
+
* regular header sort arrow. Omit to keep the backend's implicit Id DESC ordering.
|
|
86
|
+
*/
|
|
87
|
+
defaultSortField?: string;
|
|
88
|
+
/** Direction for `defaultSortField`: 1 ascending (default), -1 descending. */
|
|
89
|
+
defaultSortOrder: 1 | -1;
|
|
90
|
+
initialMultiSortMeta: SortMeta[] | null;
|
|
91
|
+
/** Columns currently rendered — `cols` minus the hidden ones. Actions columns always render. */
|
|
92
|
+
visibleCols: Column[];
|
|
93
|
+
/** Cached count of visible data columns, so template bindings don't re-derive it per CD cycle. */
|
|
94
|
+
private visibleDataColsCount;
|
|
95
|
+
/** Data columns offered in the column chooser (actions columns are excluded). */
|
|
96
|
+
chooserCols: Column[];
|
|
81
97
|
resolvedStateKey: string | null;
|
|
82
98
|
selectedItemIds: number[];
|
|
83
99
|
getAlreadySelectedItemIds: (additionalIndexes?: any) => number[];
|
|
@@ -103,6 +119,69 @@ export declare class SpiderlyDataTableComponent implements OnInit, AfterViewInit
|
|
|
103
119
|
ngAfterViewInit(): void;
|
|
104
120
|
private setupRemovableSort;
|
|
105
121
|
ngOnInit(): void;
|
|
122
|
+
/**
|
|
123
|
+
* User visibility choices (field → visible), holding only fields the user explicitly
|
|
124
|
+
* toggled away from their declared default — so a page changing a column's declared
|
|
125
|
+
* default later flows through to every user who never touched that column.
|
|
126
|
+
*/
|
|
127
|
+
private columnVisibilityOverrides;
|
|
128
|
+
/**
|
|
129
|
+
* Columns revealed by the load-time reconciliation. Kept apart from
|
|
130
|
+
* `columnVisibilityOverrides` so persisting a later unrelated toggle can't promote a
|
|
131
|
+
* transient safety reveal into a durable choice.
|
|
132
|
+
*/
|
|
133
|
+
private revealedByConstraint;
|
|
134
|
+
/** A data column shows values for a `field`; anything else (the actions column) always renders. */
|
|
135
|
+
private static isDataColumn;
|
|
136
|
+
/**
|
|
137
|
+
* Storage slot for the visibility overrides. Deliberately ALWAYS localStorage, even when
|
|
138
|
+
* `stateStorage` is 'session': the column layout is a durable preference, while filters
|
|
139
|
+
* are a transient working set — different natural lifetimes.
|
|
140
|
+
*/
|
|
141
|
+
private get columnsStateKey();
|
|
142
|
+
/** Actions columns always render; data columns follow reveal/override, then declared default. */
|
|
143
|
+
isColumnVisible(col: Column): boolean;
|
|
144
|
+
private refreshVisibleCols;
|
|
145
|
+
/**
|
|
146
|
+
* Locked columns can't be toggled; the last visible data column can't be hidden — the
|
|
147
|
+
* table must never collapse to just an actions column. Revealing is always allowed.
|
|
148
|
+
*/
|
|
149
|
+
canToggleColumn(col: Column): boolean;
|
|
150
|
+
toggleColumn(col: Column, visible: boolean): void;
|
|
151
|
+
/** Restores every column to its declared default and forgets the stored override. */
|
|
152
|
+
resetColumnVisibility(): void;
|
|
153
|
+
/**
|
|
154
|
+
* A hidden column contributes nothing to filtering or sorting: the header is the only
|
|
155
|
+
* filter surface, so a kept constraint would restrict the data invisibly. Reloads (once)
|
|
156
|
+
* only when a constraint was actually cleared — plain hides don't need a server round-trip.
|
|
157
|
+
*/
|
|
158
|
+
private clearHiddenColumnConstraints;
|
|
159
|
+
/** Whether filter metadata (single or array) carries a real constraint, not just an empty slot. */
|
|
160
|
+
private static isActiveFilterMeta;
|
|
161
|
+
private persistColumnVisibility;
|
|
162
|
+
private restoreColumnVisibility;
|
|
163
|
+
/** Parses a JSON entry from web storage; missing or corrupted entries read as null. */
|
|
164
|
+
private static readStoredJson;
|
|
165
|
+
/**
|
|
166
|
+
* PrimeNG's persisted table state (filters/sort/pagination), read directly from storage
|
|
167
|
+
* because we need it before PrimeNG's restoreState() runs on the first [value] change.
|
|
168
|
+
*/
|
|
169
|
+
private persistedTableState;
|
|
170
|
+
/**
|
|
171
|
+
* Guards the "hidden contributes nothing" invariant against state this component didn't
|
|
172
|
+
* write (older blobs, hand-edited storage): a hidden column the persisted table state
|
|
173
|
+
* still filters or sorts by is revealed rather than constraining the data invisibly.
|
|
174
|
+
* In-memory only — once the constraint is gone, the user's stored choice reapplies.
|
|
175
|
+
*/
|
|
176
|
+
private reconcileVisibilityWithPersistedConstraints;
|
|
177
|
+
/**
|
|
178
|
+
* The declared default as PrimeNG sort meta, or null when none is declared — or when its
|
|
179
|
+
* column is hidden ("hidden contributes nothing"): the table then falls back to the
|
|
180
|
+
* backend's implicit Id DESC, exactly as if no default were declared.
|
|
181
|
+
*/
|
|
182
|
+
private defaultMultiSortMeta;
|
|
183
|
+
private persistedMultiSortMeta;
|
|
184
|
+
private applyDefaultSortIfUnsorted;
|
|
106
185
|
lazyLoad(event: TableLazyLoadEvent): void;
|
|
107
186
|
clientLoad(): void;
|
|
108
187
|
private clientFilterCount;
|
|
@@ -141,7 +220,7 @@ export declare class SpiderlyDataTableComponent implements OnInit, AfterViewInit
|
|
|
141
220
|
rowUnselect(id: number): void;
|
|
142
221
|
getFormArrayControlByIndex(formControlName: string, index: number): SpiderlyFormControl;
|
|
143
222
|
static ɵfac: i0.ɵɵFactoryDeclaration<SpiderlyDataTableComponent, never>;
|
|
144
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SpiderlyDataTableComponent, "spiderly-data-table", never, { "tableTitle": { "alias": "tableTitle"; "required": false; }; "tableIcon": { "alias": "tableIcon"; "required": false; }; "items": { "alias": "items"; "required": false; }; "rows": { "alias": "rows"; "required": false; }; "cols": { "alias": "cols"; "required": false; }; "showPaginator": { "alias": "showPaginator"; "required": false; }; "showCardWrapper": { "alias": "showCardWrapper"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "idField": { "alias": "idField"; "required": false; }; "getPaginatedListObservableMethod": { "alias": "getPaginatedListObservableMethod"; "required": false; }; "exportListToExcelObservableMethod": { "alias": "exportListToExcelObservableMethod"; "required": false; }; "deleteItemFromTableObservableMethod": { "alias": "deleteItemFromTableObservableMethod"; "required": false; }; "deleteListFromTableObservableMethod": { "alias": "deleteListFromTableObservableMethod"; "required": false; }; "newlySelectedItems": { "alias": "newlySelectedItems"; "required": false; }; "unselectedItems": { "alias": "unselectedItems"; "required": false; }; "selectionMode": { "alias": "selectionMode"; "required": false; }; "selectedLazyLoadObservableMethod": { "alias": "selectedLazyLoadObservableMethod"; "required": false; }; "additionalFilterIdLong": { "alias": "additionalFilterIdLong"; "required": false; }; "showAddButton": { "alias": "showAddButton"; "required": false; }; "showExportToExcelButton": { "alias": "showExportToExcelButton"; "required": false; }; "showReloadTableButton": { "alias": "showReloadTableButton"; "required": false; }; "getFormArrayItems": { "alias": "getFormArrayItems"; "required": false; }; "hasLazyLoad": { "alias": "hasLazyLoad"; "required": false; }; "stateKey": { "alias": "stateKey"; "required": false; }; "stateStorage": { "alias": "stateStorage"; "required": false; }; "getAlreadySelectedItemIds": { "alias": "getAlreadySelectedItemIds"; "required": false; }; "getAlreadySelectedItems": { "alias": "getAlreadySelectedItems"; "required": false; }; "getFormControl": { "alias": "getFormControl"; "required": false; }; "additionalIndexes": { "alias": "additionalIndexes"; "required": false; }; "navigateOnRowClick": { "alias": "navigateOnRowClick"; "required": false; }; "rowNavigationPath": { "alias": "rowNavigationPath"; "required": false; }; }, { "onTotalRecordsChange": "onTotalRecordsChange"; "onLazyLoad": "onLazyLoad"; "onIsAllSelectedChange": "onIsAllSelectedChange"; "onRowSelect": "onRowSelect"; "onRowUnselect": "onRowUnselect"; }, ["actionsTemplate"], never, true, never>;
|
|
223
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SpiderlyDataTableComponent, "spiderly-data-table", never, { "tableTitle": { "alias": "tableTitle"; "required": false; }; "tableIcon": { "alias": "tableIcon"; "required": false; }; "items": { "alias": "items"; "required": false; }; "rows": { "alias": "rows"; "required": false; }; "cols": { "alias": "cols"; "required": false; }; "showPaginator": { "alias": "showPaginator"; "required": false; }; "showCardWrapper": { "alias": "showCardWrapper"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "idField": { "alias": "idField"; "required": false; }; "getPaginatedListObservableMethod": { "alias": "getPaginatedListObservableMethod"; "required": false; }; "exportListToExcelObservableMethod": { "alias": "exportListToExcelObservableMethod"; "required": false; }; "deleteItemFromTableObservableMethod": { "alias": "deleteItemFromTableObservableMethod"; "required": false; }; "deleteListFromTableObservableMethod": { "alias": "deleteListFromTableObservableMethod"; "required": false; }; "newlySelectedItems": { "alias": "newlySelectedItems"; "required": false; }; "unselectedItems": { "alias": "unselectedItems"; "required": false; }; "selectionMode": { "alias": "selectionMode"; "required": false; }; "selectedLazyLoadObservableMethod": { "alias": "selectedLazyLoadObservableMethod"; "required": false; }; "additionalFilterIdLong": { "alias": "additionalFilterIdLong"; "required": false; }; "showAddButton": { "alias": "showAddButton"; "required": false; }; "showExportToExcelButton": { "alias": "showExportToExcelButton"; "required": false; }; "showReloadTableButton": { "alias": "showReloadTableButton"; "required": false; }; "getFormArrayItems": { "alias": "getFormArrayItems"; "required": false; }; "hasLazyLoad": { "alias": "hasLazyLoad"; "required": false; }; "stateKey": { "alias": "stateKey"; "required": false; }; "stateStorage": { "alias": "stateStorage"; "required": false; }; "defaultSortField": { "alias": "defaultSortField"; "required": false; }; "defaultSortOrder": { "alias": "defaultSortOrder"; "required": false; }; "getAlreadySelectedItemIds": { "alias": "getAlreadySelectedItemIds"; "required": false; }; "getAlreadySelectedItems": { "alias": "getAlreadySelectedItems"; "required": false; }; "getFormControl": { "alias": "getFormControl"; "required": false; }; "additionalIndexes": { "alias": "additionalIndexes"; "required": false; }; "navigateOnRowClick": { "alias": "navigateOnRowClick"; "required": false; }; "rowNavigationPath": { "alias": "rowNavigationPath"; "required": false; }; }, { "onTotalRecordsChange": "onTotalRecordsChange"; "onLazyLoad": "onLazyLoad"; "onIsAllSelectedChange": "onIsAllSelectedChange"; "onRowSelect": "onRowSelect"; "onRowUnselect": "onRowUnselect"; }, ["actionsTemplate"], never, true, never>;
|
|
145
224
|
}
|
|
146
225
|
export declare class Action {
|
|
147
226
|
name?: string;
|
|
@@ -181,6 +260,17 @@ export declare class Column<T = any> {
|
|
|
181
260
|
showTime?: boolean;
|
|
182
261
|
decimalPlaces?: number;
|
|
183
262
|
sortable?: boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Whether the column is initially rendered. Defaults to `true`. Declare `visible: false` for
|
|
265
|
+
* columns that should be available in the column chooser but hidden until the user reveals them.
|
|
266
|
+
*/
|
|
267
|
+
visible?: boolean;
|
|
268
|
+
/**
|
|
269
|
+
* Pins the column: it always renders and shows in the chooser as checked and disabled.
|
|
270
|
+
* Use for the row's identifying column (e.g. a product's title) so the table can never
|
|
271
|
+
* lose its anchor.
|
|
272
|
+
*/
|
|
273
|
+
lockVisible?: boolean;
|
|
184
274
|
/**
|
|
185
275
|
* Fired when this column's cell is clicked. Receives a {@link CellClickEvent} with the row id,
|
|
186
276
|
* the column field, the full row, the raw and formatted cell value, the clicked `<td>` element
|
|
@@ -191,7 +281,7 @@ export declare class Column<T = any> {
|
|
|
191
281
|
* Not applied to editable cells — those belong to their inline input.
|
|
192
282
|
*/
|
|
193
283
|
onCellClick?: (event: CellClickEvent) => void;
|
|
194
|
-
constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, onCellClick, }?: {
|
|
284
|
+
constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, visible, lockVisible, onCellClick, }?: {
|
|
195
285
|
name?: string;
|
|
196
286
|
field?: string & keyof T;
|
|
197
287
|
filterField?: string & keyof T;
|
|
@@ -205,6 +295,8 @@ export declare class Column<T = any> {
|
|
|
205
295
|
showTime?: boolean;
|
|
206
296
|
decimalPlaces?: number;
|
|
207
297
|
sortable?: boolean;
|
|
298
|
+
visible?: boolean;
|
|
299
|
+
lockVisible?: boolean;
|
|
208
300
|
onCellClick?: (event: CellClickEvent) => void;
|
|
209
301
|
});
|
|
210
302
|
}
|
package/package.json
CHANGED
|
@@ -43,6 +43,32 @@
|
|
|
43
43
|
text-decoration: underline;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
.column-chooser {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: 8px;
|
|
50
|
+
}
|
|
51
|
+
.column-chooser-option {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: 8px;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
}
|
|
57
|
+
.column-chooser-reset {
|
|
58
|
+
margin-top: 4px;
|
|
59
|
+
padding: 0;
|
|
60
|
+
border: none;
|
|
61
|
+
background: none;
|
|
62
|
+
color: var(--p-primary-color);
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
align-self: flex-start;
|
|
65
|
+
font-size: 0.875rem;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
text-decoration: underline;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
46
72
|
::ng-deep {
|
|
47
73
|
.p-datatable-thead {
|
|
48
74
|
position: unset !important;
|