@toolbox-web/grid-angular 1.3.1 → 1.4.1
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 +146 -54
- package/fesm2022/toolbox-web-grid-angular-features-clipboard.mjs +58 -0
- package/fesm2022/toolbox-web-grid-angular-features-clipboard.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-column-virtualization.mjs +37 -0
- package/fesm2022/toolbox-web-grid-angular-features-column-virtualization.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-context-menu.mjs +51 -0
- package/fesm2022/toolbox-web-grid-angular-features-context-menu.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-editing.mjs +115 -1
- package/fesm2022/toolbox-web-grid-angular-features-editing.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs +55 -2
- package/fesm2022/toolbox-web-grid-angular-features-export.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs +159 -5
- package/fesm2022/toolbox-web-grid-angular-features-filtering.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs +83 -0
- package/fesm2022/toolbox-web-grid-angular-features-grouping-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs +82 -0
- package/fesm2022/toolbox-web-grid-angular-features-grouping-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs +115 -2
- package/fesm2022/toolbox-web-grid-angular-features-master-detail.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-multi-sort.mjs +38 -0
- package/fesm2022/toolbox-web-grid-angular-features-multi-sort.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pinned-columns.mjs +37 -0
- package/fesm2022/toolbox-web-grid-angular-features-pinned-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs +103 -0
- package/fesm2022/toolbox-web-grid-angular-features-pinned-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-pivot.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-pivot.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs +58 -2
- package/fesm2022/toolbox-web-grid-angular-features-print.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-reorder-columns.mjs +52 -0
- package/fesm2022/toolbox-web-grid-angular-features-reorder-columns.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-reorder-rows.mjs +41 -0
- package/fesm2022/toolbox-web-grid-angular-features-reorder-rows.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs +112 -2
- package/fesm2022/toolbox-web-grid-angular-features-responsive.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-row-drag-drop.mjs +77 -0
- package/fesm2022/toolbox-web-grid-angular-features-row-drag-drop.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs +52 -2
- package/fesm2022/toolbox-web-grid-angular-features-selection.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-server-side.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-server-side.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-tooltip.mjs +36 -0
- package/fesm2022/toolbox-web-grid-angular-features-tooltip.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-tree.mjs +53 -0
- package/fesm2022/toolbox-web-grid-angular-features-tree.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs +57 -2
- package/fesm2022/toolbox-web-grid-angular-features-undo-redo.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular-features-visibility.mjs +53 -0
- package/fesm2022/toolbox-web-grid-angular-features-visibility.mjs.map +1 -1
- package/fesm2022/toolbox-web-grid-angular.mjs +1274 -727
- package/fesm2022/toolbox-web-grid-angular.mjs.map +1 -1
- package/package.json +1 -1
- package/types/toolbox-web-grid-angular-features-clipboard.d.ts +23 -0
- package/types/toolbox-web-grid-angular-features-clipboard.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-column-virtualization.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-column-virtualization.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-context-menu.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-context-menu.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-editing.d.ts +32 -0
- package/types/toolbox-web-grid-angular-features-editing.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-export.d.ts +21 -3
- package/types/toolbox-web-grid-angular-features-export.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-filtering.d.ts +67 -6
- package/types/toolbox-web-grid-angular-features-filtering.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-grouping-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts +25 -0
- package/types/toolbox-web-grid-angular-features-grouping-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts +23 -0
- package/types/toolbox-web-grid-angular-features-master-detail.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-multi-sort.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-multi-sort.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pinned-columns.d.ts +18 -0
- package/types/toolbox-web-grid-angular-features-pinned-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-pinned-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-pivot.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-pivot.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-print.d.ts +22 -3
- package/types/toolbox-web-grid-angular-features-print.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-reorder-columns.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-reorder-columns.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-reorder-rows.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-reorder-rows.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-responsive.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-responsive.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-row-drag-drop.d.ts +27 -0
- package/types/toolbox-web-grid-angular-features-row-drag-drop.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-selection.d.ts +21 -3
- package/types/toolbox-web-grid-angular-features-selection.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-server-side.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-server-side.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-tooltip.d.ts +19 -0
- package/types/toolbox-web-grid-angular-features-tooltip.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-tree.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-tree.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts +22 -3
- package/types/toolbox-web-grid-angular-features-undo-redo.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular-features-visibility.d.ts +22 -0
- package/types/toolbox-web-grid-angular-features-visibility.d.ts.map +1 -1
- package/types/toolbox-web-grid-angular.d.ts +939 -128
- package/types/toolbox-web-grid-angular.d.ts.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, contentChild, TemplateRef, effect, Directive,
|
|
2
|
+
import { inject, ElementRef, contentChild, TemplateRef, effect, Directive, DestroyRef, input, InjectionToken, Injectable, makeEnvironmentProviders, createComponent, signal, afterNextRender, computed, output, EnvironmentInjector, ApplicationRef, ViewContainerRef } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { FormGroup } from '@angular/forms';
|
|
5
5
|
import { startWith, debounceTime } from 'rxjs/operators';
|
|
@@ -18,6 +18,7 @@ import { DataGridElement } from '@toolbox-web/grid';
|
|
|
18
18
|
*
|
|
19
19
|
* Also checks if it's an ES6 class (vs function) by inspecting the
|
|
20
20
|
* string representation.
|
|
21
|
+
* @since 0.3.0
|
|
21
22
|
*/
|
|
22
23
|
function isComponentClass(value) {
|
|
23
24
|
if (typeof value !== 'function' || value.prototype === undefined) {
|
|
@@ -85,6 +86,14 @@ function getEditorTemplate(element) {
|
|
|
85
86
|
* ```
|
|
86
87
|
*
|
|
87
88
|
* @category Directive
|
|
89
|
+
*
|
|
90
|
+
* MOVE-IN-V2: this directive (and its companion `GridEditorContext` type and
|
|
91
|
+
* `getEditorTemplate` helper) will physically move into
|
|
92
|
+
* `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
|
|
93
|
+
* re-exports from the main `@toolbox-web/grid-angular` entry will be removed
|
|
94
|
+
* at the same time. Consumers should already be importing from the feature
|
|
95
|
+
* entry.
|
|
96
|
+
* @since 0.1.0
|
|
88
97
|
*/
|
|
89
98
|
class GridColumnEditor {
|
|
90
99
|
elementRef = inject((ElementRef));
|
|
@@ -159,6 +168,7 @@ function getViewTemplate(element) {
|
|
|
159
168
|
* ```
|
|
160
169
|
*
|
|
161
170
|
* @category Directive
|
|
171
|
+
* @since 0.1.0
|
|
162
172
|
*/
|
|
163
173
|
class GridColumnView {
|
|
164
174
|
elementRef = inject((ElementRef));
|
|
@@ -189,124 +199,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
189
199
|
args: [{ selector: 'tbw-grid-column-view' }]
|
|
190
200
|
}], propDecorators: { template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
191
201
|
|
|
192
|
-
// Global registry mapping DOM elements to their templates
|
|
193
|
-
const detailTemplateRegistry = new Map();
|
|
194
|
-
/**
|
|
195
|
-
* Gets the detail template registered for a given grid element.
|
|
196
|
-
* Used by AngularGridAdapter to retrieve templates at render time.
|
|
197
|
-
*/
|
|
198
|
-
function getDetailTemplate(gridElement) {
|
|
199
|
-
// Look for tbw-grid-detail child and get its template
|
|
200
|
-
const detailElement = gridElement.querySelector('tbw-grid-detail');
|
|
201
|
-
if (detailElement) {
|
|
202
|
-
return detailTemplateRegistry.get(detailElement);
|
|
203
|
-
}
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Gets the configuration for the detail view.
|
|
208
|
-
*/
|
|
209
|
-
function getDetailConfig(gridElement) {
|
|
210
|
-
const detailElement = gridElement.querySelector('tbw-grid-detail');
|
|
211
|
-
if (detailElement) {
|
|
212
|
-
const animationAttr = detailElement.getAttribute('animation');
|
|
213
|
-
let animation = 'slide';
|
|
214
|
-
if (animationAttr === 'false') {
|
|
215
|
-
animation = false;
|
|
216
|
-
}
|
|
217
|
-
else if (animationAttr === 'fade') {
|
|
218
|
-
animation = 'fade';
|
|
219
|
-
}
|
|
220
|
-
return {
|
|
221
|
-
showExpandColumn: detailElement.getAttribute('showExpandColumn') !== 'false',
|
|
222
|
-
animation,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Directive that captures an `<ng-template>` for use as a master-detail row renderer.
|
|
229
|
-
*
|
|
230
|
-
* This enables declarative Angular component usage for expandable detail rows
|
|
231
|
-
* that appear below the main row when expanded.
|
|
232
|
-
*
|
|
233
|
-
* ## Usage
|
|
234
|
-
*
|
|
235
|
-
* ```html
|
|
236
|
-
* <tbw-grid [rows]="rows" [gridConfig]="config">
|
|
237
|
-
* <tbw-grid-detail [showExpandColumn]="true" animation="slide">
|
|
238
|
-
* <ng-template let-row>
|
|
239
|
-
* <app-detail-panel [employee]="row" />
|
|
240
|
-
* </ng-template>
|
|
241
|
-
* </tbw-grid-detail>
|
|
242
|
-
* </tbw-grid>
|
|
243
|
-
* ```
|
|
244
|
-
*
|
|
245
|
-
* The template context provides:
|
|
246
|
-
* - `$implicit` / `row`: The full row data object
|
|
247
|
-
*
|
|
248
|
-
* Import the directive in your component:
|
|
249
|
-
*
|
|
250
|
-
* ```typescript
|
|
251
|
-
* import { GridDetailView } from '@toolbox-web/grid-angular';
|
|
252
|
-
*
|
|
253
|
-
* @Component({
|
|
254
|
-
* imports: [GridDetailView],
|
|
255
|
-
* // ...
|
|
256
|
-
* })
|
|
257
|
-
* ```
|
|
258
|
-
*
|
|
259
|
-
* @example
|
|
260
|
-
* ```html
|
|
261
|
-
* <tbw-grid [rows]="rows" [gridConfig]="config">
|
|
262
|
-
* <tbw-grid-detail [showExpandColumn]="true" animation="slide">
|
|
263
|
-
* <ng-template let-row>
|
|
264
|
-
* <app-detail-panel [employee]="row" />
|
|
265
|
-
* </ng-template>
|
|
266
|
-
* </tbw-grid-detail>
|
|
267
|
-
* </tbw-grid>
|
|
268
|
-
* ```
|
|
269
|
-
*
|
|
270
|
-
* @category Directive
|
|
271
|
-
*/
|
|
272
|
-
class GridDetailView {
|
|
273
|
-
elementRef = inject((ElementRef));
|
|
274
|
-
/** Whether to show the expand/collapse column. Default: true */
|
|
275
|
-
showExpandColumn = input(true, ...(ngDevMode ? [{ debugName: "showExpandColumn" }] : /* istanbul ignore next */ []));
|
|
276
|
-
/** Animation style for expand/collapse. Default: 'slide' */
|
|
277
|
-
animation = input('slide', ...(ngDevMode ? [{ debugName: "animation" }] : /* istanbul ignore next */ []));
|
|
278
|
-
/**
|
|
279
|
-
* Query for the ng-template content child.
|
|
280
|
-
*/
|
|
281
|
-
template = contentChild((TemplateRef), ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
|
|
282
|
-
/** Effect that triggers when the template is available */
|
|
283
|
-
onTemplateReceived = effect(() => {
|
|
284
|
-
const template = this.template();
|
|
285
|
-
if (template) {
|
|
286
|
-
// Register the template for this element
|
|
287
|
-
detailTemplateRegistry.set(this.elementRef.nativeElement, template);
|
|
288
|
-
}
|
|
289
|
-
}, ...(ngDevMode ? [{ debugName: "onTemplateReceived" }] : /* istanbul ignore next */ []));
|
|
290
|
-
/**
|
|
291
|
-
* Static type guard for template context.
|
|
292
|
-
* Enables type inference in templates.
|
|
293
|
-
*/
|
|
294
|
-
static ngTemplateContextGuard(dir, ctx) {
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
297
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridDetailView, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
298
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.5", type: GridDetailView, isStandalone: true, selector: "tbw-grid-detail", inputs: { showExpandColumn: { classPropertyName: "showExpandColumn", publicName: "showExpandColumn", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "template", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], ngImport: i0 });
|
|
299
|
-
}
|
|
300
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridDetailView, decorators: [{
|
|
301
|
-
type: Directive,
|
|
302
|
-
args: [{ selector: 'tbw-grid-detail' }]
|
|
303
|
-
}], propDecorators: { showExpandColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExpandColumn", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
304
|
-
|
|
305
202
|
// Symbol for storing form context on the grid element
|
|
306
203
|
const FORM_ARRAY_CONTEXT$1 = Symbol('formArrayContext');
|
|
307
204
|
/**
|
|
308
205
|
* Gets the FormArrayContext from a grid element, if present.
|
|
309
206
|
* @internal
|
|
207
|
+
* @since 0.5.0
|
|
310
208
|
*/
|
|
311
209
|
function getFormArrayContext(gridElement) {
|
|
312
210
|
return gridElement[FORM_ARRAY_CONTEXT$1];
|
|
@@ -370,6 +268,14 @@ function getFormArrayContext(gridElement) {
|
|
|
370
268
|
* ```
|
|
371
269
|
*
|
|
372
270
|
* @category Directive
|
|
271
|
+
*
|
|
272
|
+
* MOVE-IN-V2: this directive (and its `FormArrayContext` type and
|
|
273
|
+
* `getFormArrayContext` helper) will physically move into
|
|
274
|
+
* `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
|
|
275
|
+
* re-exports from the main `@toolbox-web/grid-angular` entry will be removed
|
|
276
|
+
* at the same time. Consumers should already be importing from the feature
|
|
277
|
+
* entry.
|
|
278
|
+
* @since 0.5.0
|
|
373
279
|
*/
|
|
374
280
|
class GridFormArray {
|
|
375
281
|
destroyRef = inject(DestroyRef);
|
|
@@ -785,88 +691,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
785
691
|
}]
|
|
786
692
|
}], propDecorators: { formArray: [{ type: i0.Input, args: [{ isSignal: true, alias: "formArray", required: true }] }], syncValidation: [{ type: i0.Input, args: [{ isSignal: true, alias: "syncValidation", required: false }] }] } });
|
|
787
693
|
|
|
788
|
-
/**
|
|
789
|
-
* Registry to store responsive card templates by grid element.
|
|
790
|
-
* Used by AngularGridAdapter to create card renderers.
|
|
791
|
-
*/
|
|
792
|
-
const responsiveCardTemplateRegistry = new Map();
|
|
793
|
-
/**
|
|
794
|
-
* Retrieves the responsive card template for a grid element.
|
|
795
|
-
*
|
|
796
|
-
* @param gridElement - The grid element to look up
|
|
797
|
-
* @returns The template reference or undefined if not found
|
|
798
|
-
*/
|
|
799
|
-
function getResponsiveCardTemplate(gridElement) {
|
|
800
|
-
// Find the tbw-grid-responsive-card element inside the grid
|
|
801
|
-
const cardElement = gridElement.querySelector('tbw-grid-responsive-card');
|
|
802
|
-
if (!cardElement)
|
|
803
|
-
return undefined;
|
|
804
|
-
return responsiveCardTemplateRegistry.get(cardElement);
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* Directive for providing custom Angular templates for responsive card layout.
|
|
808
|
-
*
|
|
809
|
-
* Use this directive to define how each row should render when the grid
|
|
810
|
-
* is in responsive/mobile mode. The template receives the row data and index.
|
|
811
|
-
*
|
|
812
|
-
* ## Usage
|
|
813
|
-
*
|
|
814
|
-
* ```html
|
|
815
|
-
* <tbw-grid [rows]="employees">
|
|
816
|
-
* <tbw-grid-responsive-card>
|
|
817
|
-
* <ng-template let-employee let-idx="index">
|
|
818
|
-
* <div class="employee-card">
|
|
819
|
-
* <img [src]="employee.avatar" alt="">
|
|
820
|
-
* <div class="info">
|
|
821
|
-
* <strong>{{ employee.name }}</strong>
|
|
822
|
-
* <span>{{ employee.department }}</span>
|
|
823
|
-
* </div>
|
|
824
|
-
* </div>
|
|
825
|
-
* </ng-template>
|
|
826
|
-
* </tbw-grid-responsive-card>
|
|
827
|
-
* </tbw-grid>
|
|
828
|
-
* ```
|
|
829
|
-
*
|
|
830
|
-
* ## Important Notes
|
|
831
|
-
*
|
|
832
|
-
* - The ResponsivePlugin must be added to your grid config
|
|
833
|
-
* - The Grid directive will automatically configure the plugin's cardRenderer
|
|
834
|
-
* - Template context provides `$implicit` (row), `row`, and `index`
|
|
835
|
-
*
|
|
836
|
-
* @see ResponsivePlugin
|
|
837
|
-
* @category Directive
|
|
838
|
-
*/
|
|
839
|
-
class GridResponsiveCard {
|
|
840
|
-
elementRef = inject((ElementRef));
|
|
841
|
-
/**
|
|
842
|
-
* The ng-template containing the card content.
|
|
843
|
-
*/
|
|
844
|
-
template = contentChild((TemplateRef), ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
|
|
845
|
-
/**
|
|
846
|
-
* Effect that registers the template when it becomes available.
|
|
847
|
-
*/
|
|
848
|
-
onTemplateReceived = effect(() => {
|
|
849
|
-
const template = this.template();
|
|
850
|
-
if (template) {
|
|
851
|
-
responsiveCardTemplateRegistry.set(this.elementRef.nativeElement, template);
|
|
852
|
-
}
|
|
853
|
-
}, ...(ngDevMode ? [{ debugName: "onTemplateReceived" }] : /* istanbul ignore next */ []));
|
|
854
|
-
/**
|
|
855
|
-
* Type guard for template context inference.
|
|
856
|
-
*/
|
|
857
|
-
static ngTemplateContextGuard(_directive, context) {
|
|
858
|
-
return true;
|
|
859
|
-
}
|
|
860
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridResponsiveCard, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
861
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.5", type: GridResponsiveCard, isStandalone: true, selector: "tbw-grid-responsive-card", queries: [{ propertyName: "template", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], ngImport: i0 });
|
|
862
|
-
}
|
|
863
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridResponsiveCard, decorators: [{
|
|
864
|
-
type: Directive,
|
|
865
|
-
args: [{
|
|
866
|
-
selector: 'tbw-grid-responsive-card',
|
|
867
|
-
}]
|
|
868
|
-
}], propDecorators: { template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
869
|
-
|
|
870
694
|
// Global registry mapping DOM elements to their templates
|
|
871
695
|
const toolPanelTemplateRegistry = new Map();
|
|
872
696
|
/**
|
|
@@ -941,6 +765,7 @@ function getToolPanelElements(gridElement) {
|
|
|
941
765
|
* ```
|
|
942
766
|
*
|
|
943
767
|
* @category Directive
|
|
768
|
+
* @since 0.1.0
|
|
944
769
|
*/
|
|
945
770
|
class GridToolPanel {
|
|
946
771
|
elementRef = inject((ElementRef));
|
|
@@ -1077,6 +902,7 @@ function getStructuralEditorTemplate(columnElement) {
|
|
|
1077
902
|
* ```
|
|
1078
903
|
*
|
|
1079
904
|
* @category Directive
|
|
905
|
+
* @since 0.1.1
|
|
1080
906
|
*/
|
|
1081
907
|
class TbwRenderer {
|
|
1082
908
|
template = inject((TemplateRef));
|
|
@@ -1173,6 +999,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1173
999
|
* ```
|
|
1174
1000
|
*
|
|
1175
1001
|
* @category Directive
|
|
1002
|
+
*
|
|
1003
|
+
* MOVE-IN-V2: this directive (and its `StructuralEditorContext` type) will
|
|
1004
|
+
* physically move into `@toolbox-web/grid-angular/features/editing` in v2.0.0;
|
|
1005
|
+
* the deprecated re-export from the main `@toolbox-web/grid-angular` entry
|
|
1006
|
+
* will be removed at the same time. Consumers should already be importing
|
|
1007
|
+
* from the feature entry. (`TbwRenderer` stays in the main entry — it is
|
|
1008
|
+
* editor-agnostic.)
|
|
1009
|
+
* @since 0.1.1
|
|
1176
1010
|
*/
|
|
1177
1011
|
class TbwEditor {
|
|
1178
1012
|
template = inject((TemplateRef));
|
|
@@ -1214,6 +1048,72 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1214
1048
|
args: [{ selector: '[tbwEditor]' }]
|
|
1215
1049
|
}], ctorParameters: () => [] });
|
|
1216
1050
|
|
|
1051
|
+
/**
|
|
1052
|
+
* Editor mount hook registry — append-only hooks called when an Angular-managed
|
|
1053
|
+
* editor host is mounted into the DOM with a known owner grid.
|
|
1054
|
+
*
|
|
1055
|
+
* This is the augmentation point that lets feature secondary entries
|
|
1056
|
+
* (e.g. `@toolbox-web/grid-angular/features/editing`) install per-editor
|
|
1057
|
+
* lifecycle behaviour (such as the `before-edit-close` blur bridge)
|
|
1058
|
+
* without coupling the central adapter file to the editing feature.
|
|
1059
|
+
* Mirrors React's and Vue's `editor-mount-hooks` and how core grid plugins
|
|
1060
|
+
* augment the grid via `registerPlugin()`.
|
|
1061
|
+
*
|
|
1062
|
+
* @packageDocumentation
|
|
1063
|
+
* @internal
|
|
1064
|
+
*/
|
|
1065
|
+
const editorMountHooks = [];
|
|
1066
|
+
/**
|
|
1067
|
+
* Install an editor-mount hook. Called by feature secondary entries
|
|
1068
|
+
* (e.g. `features/editing`) on import.
|
|
1069
|
+
*
|
|
1070
|
+
* @internal Plugin API
|
|
1071
|
+
* @since 1.4.0
|
|
1072
|
+
*/
|
|
1073
|
+
function registerEditorMountHook(hook) {
|
|
1074
|
+
editorMountHooks.push(hook);
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Run all registered editor-mount hooks for a freshly mounted editor.
|
|
1078
|
+
* Returns a combined teardown that invokes each hook's teardown in
|
|
1079
|
+
* registration order.
|
|
1080
|
+
*
|
|
1081
|
+
* @internal Adapter use only.
|
|
1082
|
+
*/
|
|
1083
|
+
function notifyEditorMounted(container, gridEl) {
|
|
1084
|
+
const teardowns = [];
|
|
1085
|
+
for (const hook of editorMountHooks) {
|
|
1086
|
+
const teardown = hook({ container, gridEl });
|
|
1087
|
+
if (teardown)
|
|
1088
|
+
teardowns.push(teardown);
|
|
1089
|
+
}
|
|
1090
|
+
return () => {
|
|
1091
|
+
for (const teardown of teardowns)
|
|
1092
|
+
teardown();
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Returns a function that, when invoked, blurs the focused input/textarea/select
|
|
1097
|
+
* inside `host` (if any). Used by the `before-edit-close` bridge installed by
|
|
1098
|
+
* `@toolbox-web/grid-angular/features/editing` so editors that commit on
|
|
1099
|
+
* `(blur)` flush their pending value before the cell DOM is torn down by Tab /
|
|
1100
|
+
* programmatic row exit.
|
|
1101
|
+
* @internal
|
|
1102
|
+
* @since 1.4.0
|
|
1103
|
+
*/
|
|
1104
|
+
function makeFlushFocusedInput(host) {
|
|
1105
|
+
return () => {
|
|
1106
|
+
const focused = host.ownerDocument.activeElement;
|
|
1107
|
+
if (focused &&
|
|
1108
|
+
host.contains(focused) &&
|
|
1109
|
+
(focused instanceof HTMLInputElement ||
|
|
1110
|
+
focused instanceof HTMLTextAreaElement ||
|
|
1111
|
+
focused instanceof HTMLSelectElement)) {
|
|
1112
|
+
focused.blur();
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1217
1117
|
/**
|
|
1218
1118
|
* Editor Wiring Helpers
|
|
1219
1119
|
*
|
|
@@ -1304,6 +1204,7 @@ function wireEditorCallbacks(hostElement, instance, commit, cancel) {
|
|
|
1304
1204
|
*/
|
|
1305
1205
|
/**
|
|
1306
1206
|
* Injection token for providing type defaults at app level.
|
|
1207
|
+
* @since 0.3.0
|
|
1307
1208
|
*/
|
|
1308
1209
|
const GRID_TYPE_DEFAULTS = new InjectionToken('GRID_TYPE_DEFAULTS');
|
|
1309
1210
|
/**
|
|
@@ -1341,6 +1242,7 @@ const GRID_TYPE_DEFAULTS = new InjectionToken('GRID_TYPE_DEFAULTS');
|
|
|
1341
1242
|
* }
|
|
1342
1243
|
* }
|
|
1343
1244
|
* ```
|
|
1245
|
+
* @since 0.3.0
|
|
1344
1246
|
*/
|
|
1345
1247
|
class GridTypeRegistry {
|
|
1346
1248
|
defaults = new Map();
|
|
@@ -1430,11 +1332,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1430
1332
|
* ]
|
|
1431
1333
|
* };
|
|
1432
1334
|
* ```
|
|
1335
|
+
* @since 0.3.0
|
|
1433
1336
|
*/
|
|
1434
1337
|
function provideGridTypeDefaults(defaults) {
|
|
1435
1338
|
return makeEnvironmentProviders([{ provide: GRID_TYPE_DEFAULTS, useValue: defaults }]);
|
|
1436
1339
|
}
|
|
1437
1340
|
|
|
1341
|
+
/**
|
|
1342
|
+
* Append-only bridge registries used by `@toolbox-web/grid-angular`.
|
|
1343
|
+
*
|
|
1344
|
+
* These let feature secondary entries plug into the central `GridAdapter`
|
|
1345
|
+
* without the adapter needing to know about them. Mirrors React's and Vue's
|
|
1346
|
+
* `register*Bridge` modules and how core grid plugins augment the grid via
|
|
1347
|
+
* `registerPlugin()`.
|
|
1348
|
+
*
|
|
1349
|
+
* This module is deliberately framework-free: it holds plain module-level
|
|
1350
|
+
* `let` state and never imports from `@angular/core` or from
|
|
1351
|
+
* `@toolbox-web/grid/plugins/...`. Feature subpaths import the setters via
|
|
1352
|
+
* the `@toolbox-web/grid-angular` package barrel (relative imports outside
|
|
1353
|
+
* a secondary entry's `rootDir` are forbidden by ng-packagr).
|
|
1354
|
+
*
|
|
1355
|
+
* @internal
|
|
1356
|
+
*/
|
|
1357
|
+
let detailRendererBridge = null;
|
|
1358
|
+
let responsiveCardRendererBridge = null;
|
|
1359
|
+
let filterPanelTypeDefaultBridge = null;
|
|
1360
|
+
/**
|
|
1361
|
+
* Install the master-detail row-renderer bridge. Called once on import by
|
|
1362
|
+
* `@toolbox-web/grid-angular/features/master-detail`.
|
|
1363
|
+
* @internal Plugin API
|
|
1364
|
+
* @since 1.4.0
|
|
1365
|
+
*/
|
|
1366
|
+
function registerDetailRendererBridge(bridge) {
|
|
1367
|
+
detailRendererBridge = bridge;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Install the responsive-card row-renderer bridge. Called once on import by
|
|
1371
|
+
* `@toolbox-web/grid-angular/features/responsive`.
|
|
1372
|
+
* @internal Plugin API
|
|
1373
|
+
* @since 1.4.0
|
|
1374
|
+
*/
|
|
1375
|
+
function registerResponsiveCardRendererBridge(bridge) {
|
|
1376
|
+
responsiveCardRendererBridge = bridge;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Install the type-default `filterPanelRenderer` wrapper. Called once on import
|
|
1380
|
+
* by `@toolbox-web/grid-angular/features/filtering`. Without this bridge,
|
|
1381
|
+
* type-default and grid-config-level component-class filterPanelRenderers are
|
|
1382
|
+
* silently dropped — same precondition as the FilteringPlugin (TBW031).
|
|
1383
|
+
* @internal Plugin API
|
|
1384
|
+
* @since 1.4.0
|
|
1385
|
+
*/
|
|
1386
|
+
function registerFilterPanelTypeDefaultBridge(bridge) {
|
|
1387
|
+
filterPanelTypeDefaultBridge = bridge;
|
|
1388
|
+
}
|
|
1389
|
+
/** @internal Adapter use only. */
|
|
1390
|
+
function getDetailRendererBridge() {
|
|
1391
|
+
return detailRendererBridge;
|
|
1392
|
+
}
|
|
1393
|
+
/** @internal Adapter use only. */
|
|
1394
|
+
function getResponsiveCardRendererBridge() {
|
|
1395
|
+
return responsiveCardRendererBridge;
|
|
1396
|
+
}
|
|
1397
|
+
/** @internal Adapter use only. */
|
|
1398
|
+
function getFilterPanelTypeDefaultBridge() {
|
|
1399
|
+
return filterPanelTypeDefaultBridge;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/**
|
|
1403
|
+
* Internal registries used by `@toolbox-web/grid-angular`.
|
|
1404
|
+
*
|
|
1405
|
+
* Two extension points are exposed so individual feature secondary entries
|
|
1406
|
+
* (e.g. `@toolbox-web/grid-angular/features/master-detail`) can plug into
|
|
1407
|
+
* the core `Grid` directive without the directive needing to know about them.
|
|
1408
|
+
*
|
|
1409
|
+
* - {@link registerTemplateBridge} — runs in `ngAfterContentInit` once Angular
|
|
1410
|
+
* templates inside the grid have been registered. Used to discover light-DOM
|
|
1411
|
+
* slot elements (`<tbw-grid-detail>`, `<tbw-grid-responsive-card>`, …) and
|
|
1412
|
+
* wire them to the corresponding plugin's renderer setter.
|
|
1413
|
+
* - {@link registerFeatureConfigPreprocessor} — runs inside the directive's
|
|
1414
|
+
* feature-plugin builder before `createPluginFromFeature` is called. Lets a
|
|
1415
|
+
* feature transform its config object (e.g. to convert Angular component
|
|
1416
|
+
* classes embedded in `customPanels` to renderer functions).
|
|
1417
|
+
*
|
|
1418
|
+
* Both registries are append-only and module-scoped: they are populated by
|
|
1419
|
+
* side-effect imports of feature secondary entries and consumed by the core
|
|
1420
|
+
* `Grid` directive. Order is insertion order.
|
|
1421
|
+
*
|
|
1422
|
+
* @internal — public for cross-entry-point use; not part of the supported API.
|
|
1423
|
+
*/
|
|
1424
|
+
const templateBridges = [];
|
|
1425
|
+
/**
|
|
1426
|
+
* Register a template bridge. Called by feature secondary entries at module
|
|
1427
|
+
* load (e.g. `import '@toolbox-web/grid-angular/features/master-detail'`).
|
|
1428
|
+
*
|
|
1429
|
+
* Bridges are append-only and never deduplicated; calling registration twice
|
|
1430
|
+
* for the same feature module is safe because module imports are deduplicated
|
|
1431
|
+
* by the JS loader.
|
|
1432
|
+
*
|
|
1433
|
+
* @internal
|
|
1434
|
+
* @since 1.4.0
|
|
1435
|
+
*/
|
|
1436
|
+
function registerTemplateBridge(bridge) {
|
|
1437
|
+
templateBridges.push(bridge);
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Run all registered template bridges for a grid. The directive calls this
|
|
1441
|
+
* from `ngAfterContentInit` after `refreshColumns()`. Bridges run concurrently;
|
|
1442
|
+
* errors thrown by one bridge do not stop the others.
|
|
1443
|
+
*
|
|
1444
|
+
* @internal
|
|
1445
|
+
* @since 1.4.0
|
|
1446
|
+
*/
|
|
1447
|
+
function runTemplateBridges(ctx) {
|
|
1448
|
+
for (const bridge of templateBridges) {
|
|
1449
|
+
try {
|
|
1450
|
+
const result = bridge(ctx);
|
|
1451
|
+
if (result && typeof result.catch === 'function') {
|
|
1452
|
+
result.catch((err) => {
|
|
1453
|
+
// eslint-disable-next-line no-console
|
|
1454
|
+
console.error('[tbw-grid-angular] template bridge threw:', err);
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
catch (err) {
|
|
1459
|
+
// eslint-disable-next-line no-console
|
|
1460
|
+
console.error('[tbw-grid-angular] template bridge threw:', err);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
const featureConfigPreprocessors = new Map();
|
|
1465
|
+
/**
|
|
1466
|
+
* Register a feature config preprocessor. Last registration wins (subsequent
|
|
1467
|
+
* imports of the same feature module re-register the same function, which is
|
|
1468
|
+
* a no-op).
|
|
1469
|
+
*
|
|
1470
|
+
* @internal
|
|
1471
|
+
* @since 1.4.0
|
|
1472
|
+
*/
|
|
1473
|
+
function registerFeatureConfigPreprocessor(name, fn) {
|
|
1474
|
+
featureConfigPreprocessors.set(name, fn);
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* Look up the preprocessor for a feature, if any.
|
|
1478
|
+
*
|
|
1479
|
+
* @internal
|
|
1480
|
+
* @since 1.4.0
|
|
1481
|
+
*/
|
|
1482
|
+
function getFeatureConfigPreprocessor(name) {
|
|
1483
|
+
return featureConfigPreprocessors.get(name);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// #region Feature bridge registries
|
|
1487
|
+
// (Storage lives in `./internal/feature-bridges` so feature subpaths can
|
|
1488
|
+
// install bridges without pulling Angular runtime into specs that mock
|
|
1489
|
+
// `@angular/core` — see filtering feature spec.)
|
|
1490
|
+
// #endregion
|
|
1438
1491
|
/**
|
|
1439
1492
|
* Helper to get view template from either structural directive or nested directive.
|
|
1440
1493
|
*/
|
|
@@ -1544,6 +1597,7 @@ function syncRootNodes(viewRef, container) {
|
|
|
1544
1597
|
container.replaceChildren(...rootNodes);
|
|
1545
1598
|
}
|
|
1546
1599
|
}
|
|
1600
|
+
/** @since 0.11.0 */
|
|
1547
1601
|
class GridAdapter {
|
|
1548
1602
|
injector;
|
|
1549
1603
|
appRef;
|
|
@@ -1555,20 +1609,16 @@ class GridAdapter {
|
|
|
1555
1609
|
/** Editor-specific component refs tracked separately for per-cell cleanup via releaseCell. */
|
|
1556
1610
|
editorComponentRefs = [];
|
|
1557
1611
|
/**
|
|
1558
|
-
* Per-editor
|
|
1559
|
-
* editor host element.
|
|
1560
|
-
*
|
|
1561
|
-
* The grid's editing plugin emits `before-edit-close` on the host
|
|
1562
|
-
* `<tbw-grid>` before tearing down a row's managed editors. Angular
|
|
1563
|
-
* editors that commit on `(blur)` rely on the focused input firing `blur`
|
|
1564
|
-
* naturally, but Tab / programmatic row exit rebuilds the cell DOM
|
|
1565
|
-
* synchronously without giving the focused input a chance to blur first
|
|
1566
|
-
* — pending input is silently discarded.
|
|
1612
|
+
* Per-editor mount-hook teardown functions, keyed by editor host element.
|
|
1567
1613
|
*
|
|
1568
|
-
*
|
|
1569
|
-
*
|
|
1614
|
+
* Populated by {@link runEditorMountHooks} (which invokes
|
|
1615
|
+
* {@link notifyEditorMounted}) and torn down per-cell from
|
|
1616
|
+
* {@link releaseCell}, with full sweep on {@link destroy}. The actual
|
|
1617
|
+
* lifecycle behaviour is supplied by feature secondary entries (e.g.
|
|
1618
|
+
* `@toolbox-web/grid-angular/features/editing` installs the
|
|
1619
|
+
* `before-edit-close` blur bridge).
|
|
1570
1620
|
*/
|
|
1571
|
-
|
|
1621
|
+
editorMountTeardowns = new Map();
|
|
1572
1622
|
typeRegistry = null;
|
|
1573
1623
|
constructor(injector, appRef, viewContainerRef) {
|
|
1574
1624
|
this.injector = injector;
|
|
@@ -1656,9 +1706,13 @@ class GridAdapter {
|
|
|
1656
1706
|
if (config.editor && isComponentClass(config.editor)) {
|
|
1657
1707
|
processedConfig.editor = this.createComponentEditor(config.editor);
|
|
1658
1708
|
}
|
|
1659
|
-
// Convert filterPanelRenderer component class to function
|
|
1709
|
+
// Convert filterPanelRenderer component class to function via the
|
|
1710
|
+
// filtering feature bridge. Without `@toolbox-web/grid-angular/features/filtering`
|
|
1711
|
+
// imported, component-class filterPanelRenderers are dropped silently.
|
|
1660
1712
|
if (config.filterPanelRenderer && isComponentClass(config.filterPanelRenderer)) {
|
|
1661
|
-
|
|
1713
|
+
const wrapped = getFilterPanelTypeDefaultBridge()?.(config.filterPanelRenderer, this);
|
|
1714
|
+
if (wrapped)
|
|
1715
|
+
processedConfig.filterPanelRenderer = wrapped;
|
|
1662
1716
|
}
|
|
1663
1717
|
processed[type] = processedConfig;
|
|
1664
1718
|
}
|
|
@@ -1843,7 +1897,7 @@ class GridAdapter {
|
|
|
1843
1897
|
const container = document.createElement('span');
|
|
1844
1898
|
container.style.display = 'contents';
|
|
1845
1899
|
syncRootNodes(viewRef, container);
|
|
1846
|
-
this.
|
|
1900
|
+
this.runEditorMountHooks(container);
|
|
1847
1901
|
// Auto-wire: Listen for commit/cancel events on the rendered component.
|
|
1848
1902
|
// This allows components to just emit (commit) and (cancel) without
|
|
1849
1903
|
// requiring explicit template bindings like (commit)="onCommit($event)".
|
|
@@ -1869,101 +1923,40 @@ class GridAdapter {
|
|
|
1869
1923
|
};
|
|
1870
1924
|
}
|
|
1871
1925
|
/**
|
|
1872
|
-
* Creates a detail renderer function for MasterDetailPlugin.
|
|
1873
|
-
*
|
|
1926
|
+
* Creates a detail renderer function for MasterDetailPlugin. Delegates to
|
|
1927
|
+
* the bridge installed by `@toolbox-web/grid-angular/features/master-detail`.
|
|
1928
|
+
* Returns undefined if the feature is not imported or no `<tbw-grid-detail>`
|
|
1929
|
+
* template is registered for this grid.
|
|
1874
1930
|
*/
|
|
1875
1931
|
createDetailRenderer(gridElement) {
|
|
1876
|
-
|
|
1877
|
-
if (!template) {
|
|
1878
|
-
return undefined;
|
|
1879
|
-
}
|
|
1880
|
-
return (row) => {
|
|
1881
|
-
// Create the context for the template
|
|
1882
|
-
const context = {
|
|
1883
|
-
$implicit: row,
|
|
1884
|
-
row: row,
|
|
1885
|
-
};
|
|
1886
|
-
// Create embedded view from template
|
|
1887
|
-
const viewRef = this.viewContainerRef.createEmbeddedView(template, context);
|
|
1888
|
-
this.viewRefs.push(viewRef);
|
|
1889
|
-
// Trigger change detection
|
|
1890
|
-
viewRef.detectChanges();
|
|
1891
|
-
// Create a container for the root nodes
|
|
1892
|
-
const container = document.createElement('div');
|
|
1893
|
-
viewRef.rootNodes.forEach((node) => container.appendChild(node));
|
|
1894
|
-
return container;
|
|
1895
|
-
};
|
|
1932
|
+
return getDetailRendererBridge()?.(gridElement, this);
|
|
1896
1933
|
}
|
|
1897
1934
|
/**
|
|
1898
|
-
*
|
|
1899
|
-
*
|
|
1900
|
-
*
|
|
1901
|
-
* This enables MasterDetailPlugin to automatically use Angular templates
|
|
1902
|
-
* without manual configuration in the Grid directive.
|
|
1935
|
+
* FrameworkAdapter hook called by MasterDetailPlugin during attach(). Delegates
|
|
1936
|
+
* to {@link createDetailRenderer} (bridge installed by master-detail feature).
|
|
1903
1937
|
*/
|
|
1904
1938
|
parseDetailElement(detailElement) {
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
if (!template) {
|
|
1939
|
+
const gridElement = detailElement.closest('tbw-grid');
|
|
1940
|
+
if (!gridElement)
|
|
1908
1941
|
return undefined;
|
|
1909
|
-
|
|
1910
|
-
// Return a renderer function that creates embedded views
|
|
1911
|
-
// Note: rowIndex is part of the MasterDetailPlugin detailRenderer signature but not needed here
|
|
1912
|
-
return (row) => {
|
|
1913
|
-
const context = {
|
|
1914
|
-
$implicit: row,
|
|
1915
|
-
row: row,
|
|
1916
|
-
};
|
|
1917
|
-
const viewRef = this.viewContainerRef.createEmbeddedView(template, context);
|
|
1918
|
-
this.viewRefs.push(viewRef);
|
|
1919
|
-
viewRef.detectChanges();
|
|
1920
|
-
const container = document.createElement('div');
|
|
1921
|
-
viewRef.rootNodes.forEach((node) => container.appendChild(node));
|
|
1922
|
-
return container;
|
|
1923
|
-
};
|
|
1942
|
+
return getDetailRendererBridge()?.(gridElement, this);
|
|
1924
1943
|
}
|
|
1925
1944
|
/**
|
|
1926
|
-
* Creates a responsive card renderer function for ResponsivePlugin.
|
|
1927
|
-
*
|
|
1928
|
-
*
|
|
1929
|
-
* @param gridElement - The grid element to look up the template for
|
|
1930
|
-
* @returns A card renderer function or undefined if no template is found
|
|
1945
|
+
* Creates a responsive card renderer function for ResponsivePlugin. Delegates
|
|
1946
|
+
* to the bridge installed by `@toolbox-web/grid-angular/features/responsive`.
|
|
1931
1947
|
*/
|
|
1932
1948
|
createResponsiveCardRenderer(gridElement) {
|
|
1933
|
-
|
|
1934
|
-
if (!template) {
|
|
1935
|
-
return undefined;
|
|
1936
|
-
}
|
|
1937
|
-
return (row, rowIndex) => {
|
|
1938
|
-
// Create the context for the template
|
|
1939
|
-
const context = {
|
|
1940
|
-
$implicit: row,
|
|
1941
|
-
row: row,
|
|
1942
|
-
index: rowIndex,
|
|
1943
|
-
};
|
|
1944
|
-
// Create embedded view from template
|
|
1945
|
-
const viewRef = this.viewContainerRef.createEmbeddedView(template, context);
|
|
1946
|
-
this.viewRefs.push(viewRef);
|
|
1947
|
-
// Trigger change detection
|
|
1948
|
-
viewRef.detectChanges();
|
|
1949
|
-
// Create a container for the root nodes
|
|
1950
|
-
const container = document.createElement('div');
|
|
1951
|
-
viewRef.rootNodes.forEach((node) => container.appendChild(node));
|
|
1952
|
-
return container;
|
|
1953
|
-
};
|
|
1949
|
+
return getResponsiveCardRendererBridge()?.(gridElement, this);
|
|
1954
1950
|
}
|
|
1955
1951
|
/**
|
|
1956
|
-
* FrameworkAdapter hook called by ResponsivePlugin during attach().
|
|
1957
|
-
*
|
|
1958
|
-
* {@link createResponsiveCardRenderer}. Required for parity with the Vue
|
|
1959
|
-
* adapter so ResponsivePlugin's standard lookup path works for Angular
|
|
1960
|
-
* users without relying on imperative `refreshCardRenderer` calls.
|
|
1952
|
+
* FrameworkAdapter hook called by ResponsivePlugin during attach(). Delegates
|
|
1953
|
+
* to {@link createResponsiveCardRenderer} (bridge installed by responsive feature).
|
|
1961
1954
|
*/
|
|
1962
1955
|
parseResponsiveCardElement(cardElement) {
|
|
1963
1956
|
const gridElement = cardElement.closest('tbw-grid');
|
|
1964
1957
|
if (!gridElement)
|
|
1965
1958
|
return undefined;
|
|
1966
|
-
return
|
|
1959
|
+
return getResponsiveCardRendererBridge()?.(gridElement, this);
|
|
1967
1960
|
}
|
|
1968
1961
|
/**
|
|
1969
1962
|
* Creates a tool panel renderer from a light DOM element.
|
|
@@ -2047,8 +2040,11 @@ class GridAdapter {
|
|
|
2047
2040
|
typeDefault.editor = this.createComponentEditor(config.editor);
|
|
2048
2041
|
}
|
|
2049
2042
|
// Create filterPanelRenderer function that instantiates the Angular component
|
|
2043
|
+
// via the filtering feature bridge. Drop silently if the feature is not imported.
|
|
2050
2044
|
if (config.filterPanelRenderer && isComponentClass(config.filterPanelRenderer)) {
|
|
2051
|
-
|
|
2045
|
+
const wrapped = getFilterPanelTypeDefaultBridge()?.(config.filterPanelRenderer, this);
|
|
2046
|
+
if (wrapped)
|
|
2047
|
+
typeDefault.filterPanelRenderer = wrapped;
|
|
2052
2048
|
}
|
|
2053
2049
|
else if (config.filterPanelRenderer) {
|
|
2054
2050
|
typeDefault.filterPanelRenderer = config.filterPanelRenderer;
|
|
@@ -2056,47 +2052,56 @@ class GridAdapter {
|
|
|
2056
2052
|
return typeDefault;
|
|
2057
2053
|
}
|
|
2058
2054
|
/**
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
2055
|
+
* Generalized component-mount primitive. All `createComponent*Renderer` methods
|
|
2056
|
+
* are thin wrappers around this. Returns a function `(ctx) => { hostElement, componentRef }`
|
|
2057
|
+
* so callers that need the `componentRef` (editor wiring, value-change subscription)
|
|
2058
|
+
* still have it; callers that only need the host element use `.hostElement`.
|
|
2059
|
+
*
|
|
2060
|
+
* Public so feature secondary entries can compose their own component renderers
|
|
2061
|
+
* without re-implementing the mount/track plumbing.
|
|
2062
|
+
*
|
|
2063
|
+
* @param componentClass Angular component class to instantiate per call.
|
|
2064
|
+
* @param mapInputs Maps the renderer context to a `setInput()` bag.
|
|
2065
|
+
* @param pool Which `componentRefs[]` array tracks the instance for cleanup.
|
|
2066
|
+
* `'render'` (default) is the long-lived pool cleared at `dispose()`.
|
|
2067
|
+
* `'editor'` is the per-cell pool swept by `releaseCell()`.
|
|
2061
2068
|
* @internal
|
|
2062
2069
|
*/
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
if (isEditor) {
|
|
2078
|
-
this.editorComponentRefs.push(componentRef);
|
|
2079
|
-
}
|
|
2080
|
-
else {
|
|
2081
|
-
this.componentRefs.push(componentRef);
|
|
2082
|
-
}
|
|
2083
|
-
// Trigger change detection
|
|
2084
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2085
|
-
return { hostElement, componentRef };
|
|
2070
|
+
mountComponentRenderer(componentClass, mapInputs, pool = 'render') {
|
|
2071
|
+
return (ctx) => {
|
|
2072
|
+
const hostElement = document.createElement('span');
|
|
2073
|
+
hostElement.style.display = 'contents';
|
|
2074
|
+
const componentRef = createComponent(componentClass, {
|
|
2075
|
+
environmentInjector: this.injector,
|
|
2076
|
+
hostElement,
|
|
2077
|
+
});
|
|
2078
|
+
this.setComponentInputs(componentRef, mapInputs(ctx));
|
|
2079
|
+
this.appRef.attachView(componentRef.hostView);
|
|
2080
|
+
(pool === 'editor' ? this.editorComponentRefs : this.componentRefs).push(componentRef);
|
|
2081
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
2082
|
+
return { hostElement, componentRef };
|
|
2083
|
+
};
|
|
2086
2084
|
}
|
|
2087
2085
|
/**
|
|
2088
2086
|
* Creates a renderer function from an Angular component class.
|
|
2087
|
+
* Wraps {@link mountComponentRenderer} with a per-cell `WeakMap` cache so
|
|
2088
|
+
* scroll-recycled cells reuse the existing component (just refresh inputs)
|
|
2089
|
+
* instead of mounting a fresh one.
|
|
2089
2090
|
* @internal
|
|
2090
2091
|
*/
|
|
2091
2092
|
createComponentRenderer(componentClass) {
|
|
2092
|
-
// Cell cache for component-based renderers - maps cell element to its component ref
|
|
2093
2093
|
const cellCache = new WeakMap();
|
|
2094
|
+
const mount = this.mountComponentRenderer(componentClass, (ctx) => ({
|
|
2095
|
+
value: ctx.value,
|
|
2096
|
+
row: ctx.row,
|
|
2097
|
+
column: ctx.column,
|
|
2098
|
+
}));
|
|
2094
2099
|
return (ctx) => {
|
|
2095
2100
|
const cellEl = ctx.cellEl;
|
|
2096
2101
|
if (cellEl) {
|
|
2097
2102
|
const cached = cellCache.get(cellEl);
|
|
2098
2103
|
if (cached) {
|
|
2099
|
-
// Reuse existing component - just update inputs
|
|
2104
|
+
// Reuse existing component - just update inputs.
|
|
2100
2105
|
this.setComponentInputs(cached.componentRef, {
|
|
2101
2106
|
value: ctx.value,
|
|
2102
2107
|
row: ctx.row,
|
|
@@ -2106,31 +2111,25 @@ class GridAdapter {
|
|
|
2106
2111
|
return cached.hostElement;
|
|
2107
2112
|
}
|
|
2108
2113
|
}
|
|
2109
|
-
const { hostElement, componentRef } =
|
|
2110
|
-
|
|
2111
|
-
row: ctx.row,
|
|
2112
|
-
column: ctx.column,
|
|
2113
|
-
});
|
|
2114
|
-
// Cache for reuse on scroll recycles
|
|
2115
|
-
if (cellEl) {
|
|
2114
|
+
const { hostElement, componentRef } = mount(ctx);
|
|
2115
|
+
if (cellEl)
|
|
2116
2116
|
cellCache.set(cellEl, { componentRef, hostElement });
|
|
2117
|
-
}
|
|
2118
2117
|
return hostElement;
|
|
2119
2118
|
};
|
|
2120
2119
|
}
|
|
2121
2120
|
/**
|
|
2122
2121
|
* Creates an editor function from an Angular component class.
|
|
2122
|
+
* Wraps {@link mountComponentRenderer} (using the `'editor'` pool for per-cell
|
|
2123
|
+
* cleanup) plus editor-specific wiring: callback bridge, mount-hook fan-out
|
|
2124
|
+
* (see {@link runEditorMountHooks}), and external value-change subscription.
|
|
2123
2125
|
* @internal
|
|
2124
2126
|
*/
|
|
2125
2127
|
createComponentEditor(componentClass) {
|
|
2128
|
+
const mount = this.mountComponentRenderer(componentClass, (ctx) => ({ value: ctx.value, row: ctx.row, column: ctx.column }), 'editor');
|
|
2126
2129
|
return (ctx) => {
|
|
2127
|
-
const { hostElement, componentRef } =
|
|
2128
|
-
value: ctx.value,
|
|
2129
|
-
row: ctx.row,
|
|
2130
|
-
column: ctx.column,
|
|
2131
|
-
}, true);
|
|
2130
|
+
const { hostElement, componentRef } = mount(ctx);
|
|
2132
2131
|
wireEditorCallbacks(hostElement, componentRef.instance, (value) => ctx.commit(value), () => ctx.cancel());
|
|
2133
|
-
this.
|
|
2132
|
+
this.runEditorMountHooks(hostElement);
|
|
2134
2133
|
// Auto-update editor when value changes externally (e.g., via updateRow cascade
|
|
2135
2134
|
// or Escape-revert). Update the component input and run detectChanges() —
|
|
2136
2135
|
// the component's own template handles rendering regardless of editor type.
|
|
@@ -2155,179 +2154,30 @@ class GridAdapter {
|
|
|
2155
2154
|
/**
|
|
2156
2155
|
* Creates a header renderer function from an Angular component class.
|
|
2157
2156
|
* Mounts the component with full header context (column, value, sortState, etc.).
|
|
2158
|
-
* @internal
|
|
2159
|
-
*/
|
|
2160
|
-
createComponentHeaderRenderer(componentClass) {
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
};
|
|
2181
|
-
|
|
2182
|
-
/**
|
|
2183
|
-
* Creates a header label renderer function from an Angular component class.
|
|
2184
|
-
* Mounts the component with label context (column, value).
|
|
2185
|
-
* @internal
|
|
2186
|
-
*/
|
|
2187
|
-
createComponentHeaderLabelRenderer(componentClass) {
|
|
2188
|
-
return (ctx) => {
|
|
2189
|
-
const hostElement = document.createElement('span');
|
|
2190
|
-
hostElement.style.display = 'contents';
|
|
2191
|
-
const componentRef = createComponent(componentClass, {
|
|
2192
|
-
environmentInjector: this.injector,
|
|
2193
|
-
hostElement,
|
|
2194
|
-
});
|
|
2195
|
-
this.setComponentInputs(componentRef, {
|
|
2196
|
-
column: ctx.column,
|
|
2197
|
-
value: ctx.value,
|
|
2198
|
-
});
|
|
2199
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2200
|
-
this.componentRefs.push(componentRef);
|
|
2201
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2202
|
-
return hostElement;
|
|
2203
|
-
};
|
|
2204
|
-
}
|
|
2205
|
-
/**
|
|
2206
|
-
* Creates a group header renderer function from an Angular component class.
|
|
2207
|
-
*
|
|
2208
|
-
* The component should accept group header inputs (id, label, columns, firstIndex, isImplicit).
|
|
2209
|
-
* Returns the host element directly (groupHeaderRenderer returns an element, not void).
|
|
2210
|
-
* @internal
|
|
2211
|
-
*/
|
|
2212
|
-
createComponentGroupHeaderRenderer(componentClass) {
|
|
2213
|
-
return (params) => {
|
|
2214
|
-
const hostElement = document.createElement('span');
|
|
2215
|
-
hostElement.style.display = 'contents';
|
|
2216
|
-
const componentRef = createComponent(componentClass, {
|
|
2217
|
-
environmentInjector: this.injector,
|
|
2218
|
-
hostElement,
|
|
2219
|
-
});
|
|
2220
|
-
this.setComponentInputs(componentRef, {
|
|
2221
|
-
id: params.id,
|
|
2222
|
-
label: params.label,
|
|
2223
|
-
columns: params.columns,
|
|
2224
|
-
firstIndex: params.firstIndex,
|
|
2225
|
-
isImplicit: params.isImplicit,
|
|
2226
|
-
});
|
|
2227
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2228
|
-
this.componentRefs.push(componentRef);
|
|
2229
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2230
|
-
return hostElement;
|
|
2231
|
-
};
|
|
2232
|
-
}
|
|
2233
|
-
/**
|
|
2234
|
-
* Processes a GroupingColumnsConfig, converting component class references
|
|
2235
|
-
* to actual renderer functions.
|
|
2236
|
-
*
|
|
2237
|
-
* @param config - Angular grouping columns configuration with possible component class references
|
|
2238
|
-
* @returns Processed GroupingColumnsConfig with actual renderer functions
|
|
2239
|
-
*/
|
|
2240
|
-
processGroupingColumnsConfig(config) {
|
|
2241
|
-
const processed = { ...config };
|
|
2242
|
-
let changed = false;
|
|
2243
|
-
// Bridge top-level groupHeaderRenderer component class
|
|
2244
|
-
if (config.groupHeaderRenderer && isComponentClass(config.groupHeaderRenderer)) {
|
|
2245
|
-
processed.groupHeaderRenderer = this.createComponentGroupHeaderRenderer(config.groupHeaderRenderer);
|
|
2246
|
-
changed = true;
|
|
2247
|
-
}
|
|
2248
|
-
// Bridge per-group renderer component classes inside columnGroups
|
|
2249
|
-
if (Array.isArray(config.columnGroups)) {
|
|
2250
|
-
const mappedGroups = config.columnGroups.map((def) => {
|
|
2251
|
-
if (def.renderer && isComponentClass(def.renderer)) {
|
|
2252
|
-
changed = true;
|
|
2253
|
-
return { ...def, renderer: this.createComponentGroupHeaderRenderer(def.renderer) };
|
|
2254
|
-
}
|
|
2255
|
-
return def;
|
|
2256
|
-
});
|
|
2257
|
-
if (changed)
|
|
2258
|
-
processed.columnGroups = mappedGroups;
|
|
2259
|
-
}
|
|
2260
|
-
return changed ? processed : config;
|
|
2261
|
-
}
|
|
2262
|
-
/**
|
|
2263
|
-
* Processes a GroupingRowsConfig, converting component class references
|
|
2264
|
-
* to actual renderer functions.
|
|
2265
|
-
*
|
|
2266
|
-
* @param config - Angular grouping rows configuration with possible component class references
|
|
2267
|
-
* @returns Processed GroupingRowsConfig with actual renderer functions
|
|
2268
|
-
*/
|
|
2269
|
-
processGroupingRowsConfig(config) {
|
|
2270
|
-
if (config.groupRowRenderer && isComponentClass(config.groupRowRenderer)) {
|
|
2271
|
-
return {
|
|
2272
|
-
...config,
|
|
2273
|
-
groupRowRenderer: this.createComponentGroupRowRenderer(config.groupRowRenderer),
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
return config;
|
|
2277
|
-
}
|
|
2278
|
-
/**
|
|
2279
|
-
* Processes a PinnedRowsConfig, converting component class references
|
|
2280
|
-
* in `customPanels[].render` to actual renderer functions.
|
|
2281
|
-
*
|
|
2282
|
-
* @param config - Angular pinned rows configuration with possible component class references
|
|
2283
|
-
* @returns Processed PinnedRowsConfig with actual renderer functions
|
|
2284
|
-
*/
|
|
2285
|
-
processPinnedRowsConfig(config) {
|
|
2286
|
-
if (!Array.isArray(config.customPanels))
|
|
2287
|
-
return config;
|
|
2288
|
-
const hasComponentRender = config.customPanels.some((panel) => isComponentClass(panel.render));
|
|
2289
|
-
if (!hasComponentRender)
|
|
2290
|
-
return config;
|
|
2291
|
-
return {
|
|
2292
|
-
...config,
|
|
2293
|
-
customPanels: config.customPanels.map((panel) => {
|
|
2294
|
-
if (!isComponentClass(panel.render))
|
|
2295
|
-
return panel;
|
|
2296
|
-
return {
|
|
2297
|
-
...panel,
|
|
2298
|
-
render: this.createComponentPinnedRowsPanelRenderer(panel.render),
|
|
2299
|
-
};
|
|
2300
|
-
}),
|
|
2301
|
-
};
|
|
2302
|
-
}
|
|
2303
|
-
/**
|
|
2304
|
-
* Creates a pinned rows panel renderer function from an Angular component class.
|
|
2305
|
-
*
|
|
2306
|
-
* The component should accept inputs from PinnedRowsContext (totalRows, filteredRows,
|
|
2307
|
-
* selectedRows, columns, rows, grid).
|
|
2308
|
-
* @internal
|
|
2309
|
-
*/
|
|
2310
|
-
createComponentPinnedRowsPanelRenderer(componentClass) {
|
|
2311
|
-
return (ctx) => {
|
|
2312
|
-
const hostElement = document.createElement('span');
|
|
2313
|
-
hostElement.style.display = 'contents';
|
|
2314
|
-
const componentRef = createComponent(componentClass, {
|
|
2315
|
-
environmentInjector: this.injector,
|
|
2316
|
-
hostElement,
|
|
2317
|
-
});
|
|
2318
|
-
this.setComponentInputs(componentRef, {
|
|
2319
|
-
totalRows: ctx.totalRows,
|
|
2320
|
-
filteredRows: ctx.filteredRows,
|
|
2321
|
-
selectedRows: ctx.selectedRows,
|
|
2322
|
-
columns: ctx.columns,
|
|
2323
|
-
rows: ctx.rows,
|
|
2324
|
-
grid: ctx.grid,
|
|
2325
|
-
});
|
|
2326
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2327
|
-
this.componentRefs.push(componentRef);
|
|
2328
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2329
|
-
return hostElement;
|
|
2330
|
-
};
|
|
2157
|
+
* @internal
|
|
2158
|
+
*/
|
|
2159
|
+
createComponentHeaderRenderer(componentClass) {
|
|
2160
|
+
const mount = this.mountComponentRenderer(componentClass, (ctx) => ({
|
|
2161
|
+
column: ctx.column,
|
|
2162
|
+
value: ctx.value,
|
|
2163
|
+
sortState: ctx.sortState,
|
|
2164
|
+
filterActive: ctx.filterActive,
|
|
2165
|
+
renderSortIcon: ctx.renderSortIcon,
|
|
2166
|
+
renderFilterButton: ctx.renderFilterButton,
|
|
2167
|
+
}));
|
|
2168
|
+
return (ctx) => mount(ctx).hostElement;
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Creates a header label renderer function from an Angular component class.
|
|
2172
|
+
* Mounts the component with label context (column, value).
|
|
2173
|
+
* @internal
|
|
2174
|
+
*/
|
|
2175
|
+
createComponentHeaderLabelRenderer(componentClass) {
|
|
2176
|
+
const mount = this.mountComponentRenderer(componentClass, (ctx) => ({
|
|
2177
|
+
column: ctx.column,
|
|
2178
|
+
value: ctx.value,
|
|
2179
|
+
}));
|
|
2180
|
+
return (ctx) => mount(ctx).hostElement;
|
|
2331
2181
|
}
|
|
2332
2182
|
/**
|
|
2333
2183
|
* Creates a loading renderer function from an Angular component class.
|
|
@@ -2336,78 +2186,59 @@ class GridAdapter {
|
|
|
2336
2186
|
* @internal
|
|
2337
2187
|
*/
|
|
2338
2188
|
createComponentLoadingRenderer(componentClass) {
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
hostElement.style.display = 'contents';
|
|
2342
|
-
const componentRef = createComponent(componentClass, {
|
|
2343
|
-
environmentInjector: this.injector,
|
|
2344
|
-
hostElement,
|
|
2345
|
-
});
|
|
2346
|
-
this.setComponentInputs(componentRef, {
|
|
2347
|
-
size: ctx.size,
|
|
2348
|
-
});
|
|
2349
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2350
|
-
this.componentRefs.push(componentRef);
|
|
2351
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2352
|
-
return hostElement;
|
|
2353
|
-
};
|
|
2189
|
+
const mount = this.mountComponentRenderer(componentClass, (ctx) => ({ size: ctx.size }));
|
|
2190
|
+
return (ctx) => mount(ctx).hostElement;
|
|
2354
2191
|
}
|
|
2355
2192
|
/**
|
|
2356
|
-
*
|
|
2357
|
-
*
|
|
2358
|
-
*
|
|
2359
|
-
*
|
|
2193
|
+
* Create an embedded view from a `TemplateRef` and append-track it on the
|
|
2194
|
+
* adapter's view-ref pool so it is cleaned up on `destroy()` / `unmount()`.
|
|
2195
|
+
* Public so feature secondary entries can mount Angular templates (e.g.
|
|
2196
|
+
* master-detail rows, responsive cards) without reaching into the adapter's
|
|
2197
|
+
* private `viewContainerRef` / `viewRefs`.
|
|
2360
2198
|
* @internal
|
|
2361
2199
|
*/
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
environmentInjector: this.injector,
|
|
2368
|
-
hostElement,
|
|
2369
|
-
});
|
|
2370
|
-
this.setComponentInputs(componentRef, {
|
|
2371
|
-
key: params.key,
|
|
2372
|
-
value: params.value,
|
|
2373
|
-
depth: params.depth,
|
|
2374
|
-
rows: params.rows,
|
|
2375
|
-
expanded: params.expanded,
|
|
2376
|
-
toggleExpand: params.toggleExpand,
|
|
2377
|
-
});
|
|
2378
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2379
|
-
this.componentRefs.push(componentRef);
|
|
2380
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2381
|
-
return hostElement;
|
|
2382
|
-
};
|
|
2200
|
+
createTrackedEmbeddedView(template, context) {
|
|
2201
|
+
const viewRef = this.viewContainerRef.createEmbeddedView(template, context);
|
|
2202
|
+
this.viewRefs.push(viewRef);
|
|
2203
|
+
viewRef.detectChanges();
|
|
2204
|
+
return viewRef;
|
|
2383
2205
|
}
|
|
2384
2206
|
/**
|
|
2385
|
-
*
|
|
2386
|
-
*
|
|
2387
|
-
*
|
|
2388
|
-
*
|
|
2207
|
+
* Processes a GroupingColumnsConfig. Delegates to the feature config
|
|
2208
|
+
* preprocessor installed by `@toolbox-web/grid-angular/features/grouping-columns`,
|
|
2209
|
+
* which handles converting Angular component class references to actual
|
|
2210
|
+
* renderer functions. Returns the input config unchanged if the feature
|
|
2211
|
+
* is not imported.
|
|
2212
|
+
*/
|
|
2213
|
+
processGroupingColumnsConfig(config) {
|
|
2214
|
+
return this.applyFeatureConfigPreprocessor('groupingColumns', config);
|
|
2215
|
+
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Processes a GroupingRowsConfig. Delegates to the feature config preprocessor
|
|
2218
|
+
* installed by `@toolbox-web/grid-angular/features/grouping-rows`.
|
|
2219
|
+
*/
|
|
2220
|
+
processGroupingRowsConfig(config) {
|
|
2221
|
+
return this.applyFeatureConfigPreprocessor('groupingRows', config);
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Processes a PinnedRowsConfig. Delegates to the feature config preprocessor
|
|
2225
|
+
* installed by `@toolbox-web/grid-angular/features/pinned-rows`.
|
|
2226
|
+
*/
|
|
2227
|
+
processPinnedRowsConfig(config) {
|
|
2228
|
+
return this.applyFeatureConfigPreprocessor('pinnedRows', config);
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* Run a registered feature-config preprocessor against `config`, returning
|
|
2232
|
+
* the original config unchanged when the feature is not imported.
|
|
2389
2233
|
* @internal
|
|
2390
2234
|
*/
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
});
|
|
2399
|
-
// Set params input
|
|
2400
|
-
try {
|
|
2401
|
-
componentRef.setInput('params', params);
|
|
2402
|
-
}
|
|
2403
|
-
catch {
|
|
2404
|
-
// Input doesn't exist on component — ignore
|
|
2405
|
-
}
|
|
2406
|
-
this.appRef.attachView(componentRef.hostView);
|
|
2407
|
-
this.componentRefs.push(componentRef);
|
|
2408
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
2409
|
-
container.appendChild(hostElement);
|
|
2410
|
-
};
|
|
2235
|
+
applyFeatureConfigPreprocessor(name, config) {
|
|
2236
|
+
if (!config || typeof config !== 'object')
|
|
2237
|
+
return config;
|
|
2238
|
+
const preprocessor = getFeatureConfigPreprocessor(name);
|
|
2239
|
+
if (!preprocessor)
|
|
2240
|
+
return config;
|
|
2241
|
+
return preprocessor(config, this);
|
|
2411
2242
|
}
|
|
2412
2243
|
/**
|
|
2413
2244
|
* Sets component inputs using Angular's setInput API.
|
|
@@ -2449,11 +2280,11 @@ class GridAdapter {
|
|
|
2449
2280
|
this.editorComponentRefs.splice(i, 1);
|
|
2450
2281
|
}
|
|
2451
2282
|
}
|
|
2452
|
-
// Detach
|
|
2453
|
-
for (const [hostEl, unsub] of this.
|
|
2283
|
+
// Detach editor-mount hook teardowns for editor hosts inside this cell.
|
|
2284
|
+
for (const [hostEl, unsub] of this.editorMountTeardowns) {
|
|
2454
2285
|
if (cellEl.contains(hostEl)) {
|
|
2455
2286
|
unsub();
|
|
2456
|
-
this.
|
|
2287
|
+
this.editorMountTeardowns.delete(hostEl);
|
|
2457
2288
|
}
|
|
2458
2289
|
}
|
|
2459
2290
|
}
|
|
@@ -2493,40 +2324,28 @@ class GridAdapter {
|
|
|
2493
2324
|
this.componentRefs = [];
|
|
2494
2325
|
this.editorComponentRefs.forEach((ref) => ref.destroy());
|
|
2495
2326
|
this.editorComponentRefs = [];
|
|
2496
|
-
this.
|
|
2497
|
-
this.
|
|
2327
|
+
this.editorMountTeardowns.forEach((unsub) => unsub());
|
|
2328
|
+
this.editorMountTeardowns.clear();
|
|
2498
2329
|
}
|
|
2499
2330
|
/**
|
|
2500
|
-
*
|
|
2501
|
-
*
|
|
2502
|
-
*
|
|
2503
|
-
*
|
|
2504
|
-
*
|
|
2505
|
-
* The grid is resolved lazily via `queueMicrotask` because the host is
|
|
2506
|
-
* appended to the cell *after* the editor wrapper returns. Mirror of
|
|
2507
|
-
* Vue's `attachBeforeEditCloseFlush` and React's `wrapReactEditor`
|
|
2331
|
+
* Runs every registered {@link EditorMountHook} against a freshly mounted
|
|
2332
|
+
* editor host once it has been parented to the grid. The grid is resolved
|
|
2333
|
+
* lazily via `queueMicrotask` because the host is appended to the cell
|
|
2334
|
+
* *after* the editor wrapper returns. Mirror of Vue's
|
|
2335
|
+
* `attachBeforeEditCloseFlush` and React's `wrapReactEditor`
|
|
2508
2336
|
* queueMicrotask bridge.
|
|
2337
|
+
*
|
|
2338
|
+
* Without any feature imports the hook list is empty and this is a no-op
|
|
2339
|
+
* — `before-edit-close` blur handling lives in
|
|
2340
|
+
* `@toolbox-web/grid-angular/features/editing`.
|
|
2509
2341
|
* @internal
|
|
2510
2342
|
*/
|
|
2511
|
-
|
|
2343
|
+
runEditorMountHooks(host) {
|
|
2512
2344
|
queueMicrotask(() => {
|
|
2513
2345
|
const gridEl = host.closest('tbw-grid');
|
|
2514
2346
|
if (!gridEl)
|
|
2515
2347
|
return;
|
|
2516
|
-
|
|
2517
|
-
const focused = host.ownerDocument.activeElement;
|
|
2518
|
-
if (focused &&
|
|
2519
|
-
host.contains(focused) &&
|
|
2520
|
-
(focused instanceof HTMLInputElement ||
|
|
2521
|
-
focused instanceof HTMLTextAreaElement ||
|
|
2522
|
-
focused instanceof HTMLSelectElement)) {
|
|
2523
|
-
focused.blur();
|
|
2524
|
-
}
|
|
2525
|
-
};
|
|
2526
|
-
gridEl.addEventListener('before-edit-close', flush);
|
|
2527
|
-
this.editorBeforeCloseUnsubs.set(host, () => {
|
|
2528
|
-
gridEl.removeEventListener('before-edit-close', flush);
|
|
2529
|
-
});
|
|
2348
|
+
this.editorMountTeardowns.set(host, notifyEditorMounted(host, gridEl));
|
|
2530
2349
|
});
|
|
2531
2350
|
}
|
|
2532
2351
|
}
|
|
@@ -2539,6 +2358,7 @@ class GridAdapter {
|
|
|
2539
2358
|
*/
|
|
2540
2359
|
/**
|
|
2541
2360
|
* Injection token for providing icon overrides at app level.
|
|
2361
|
+
* @since 0.8.0
|
|
2542
2362
|
*/
|
|
2543
2363
|
const GRID_ICONS = new InjectionToken('GRID_ICONS');
|
|
2544
2364
|
/**
|
|
@@ -2571,6 +2391,7 @@ const GRID_ICONS = new InjectionToken('GRID_ICONS');
|
|
|
2571
2391
|
* }
|
|
2572
2392
|
* }
|
|
2573
2393
|
* ```
|
|
2394
|
+
* @since 0.8.0
|
|
2574
2395
|
*/
|
|
2575
2396
|
class GridIconRegistry {
|
|
2576
2397
|
icons = new Map();
|
|
@@ -2669,6 +2490,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2669
2490
|
* ]
|
|
2670
2491
|
* };
|
|
2671
2492
|
* ```
|
|
2493
|
+
* @since 0.8.0
|
|
2672
2494
|
*/
|
|
2673
2495
|
function provideGridIcons(icons) {
|
|
2674
2496
|
return makeEnvironmentProviders([{ provide: GRID_ICONS, useValue: icons }]);
|
|
@@ -2713,6 +2535,7 @@ function provideGridIcons(icons) {
|
|
|
2713
2535
|
* Defaults to `'tbw-grid'` (first grid in the component). Use when the
|
|
2714
2536
|
* component contains multiple grids, e.g. `'tbw-grid.primary'` or `'#my-grid'`.
|
|
2715
2537
|
* @returns Object with grid access methods and state signals
|
|
2538
|
+
* @since 0.6.0
|
|
2716
2539
|
*/
|
|
2717
2540
|
function injectGrid(selector = 'tbw-grid') {
|
|
2718
2541
|
const elementRef = inject(ElementRef);
|
|
@@ -2788,6 +2611,12 @@ function injectGrid(selector = 'tbw-grid') {
|
|
|
2788
2611
|
const unregisterStyles = (id) => {
|
|
2789
2612
|
element()?.unregisterStyles?.(id);
|
|
2790
2613
|
};
|
|
2614
|
+
const getPlugin = (pluginClass) => {
|
|
2615
|
+
return element()?.getPlugin?.(pluginClass);
|
|
2616
|
+
};
|
|
2617
|
+
const getPluginByName = ((name) => {
|
|
2618
|
+
return element()?.getPluginByName?.(name);
|
|
2619
|
+
});
|
|
2791
2620
|
return {
|
|
2792
2621
|
element,
|
|
2793
2622
|
isReady,
|
|
@@ -2798,6 +2627,8 @@ function injectGrid(selector = 'tbw-grid') {
|
|
|
2798
2627
|
toggleGroup,
|
|
2799
2628
|
registerStyles,
|
|
2800
2629
|
unregisterStyles,
|
|
2630
|
+
getPlugin,
|
|
2631
|
+
getPluginByName,
|
|
2801
2632
|
};
|
|
2802
2633
|
}
|
|
2803
2634
|
|
|
@@ -2864,6 +2695,12 @@ function injectGrid(selector = 'tbw-grid') {
|
|
|
2864
2695
|
* ```
|
|
2865
2696
|
*
|
|
2866
2697
|
* @typeParam TRow - The row data type (available via `params().column`)
|
|
2698
|
+
*
|
|
2699
|
+
* MOVE-IN-V2: this class will physically move into
|
|
2700
|
+
* `@toolbox-web/grid-angular/features/filtering` in v2.0.0; the deprecated
|
|
2701
|
+
* re-export from the main `@toolbox-web/grid-angular` entry will be removed at
|
|
2702
|
+
* the same time. Consumers should already be importing from the feature entry.
|
|
2703
|
+
* @since 0.13.0
|
|
2867
2704
|
*/
|
|
2868
2705
|
class BaseFilterPanel {
|
|
2869
2706
|
/**
|
|
@@ -2967,6 +2804,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2967
2804
|
*
|
|
2968
2805
|
* @typeParam TRow - The row data type
|
|
2969
2806
|
* @typeParam TValue - The cell value type
|
|
2807
|
+
*
|
|
2808
|
+
* MOVE-IN-V2: this class will physically move into
|
|
2809
|
+
* `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
|
|
2810
|
+
* re-export from the main `@toolbox-web/grid-angular` entry will be removed at
|
|
2811
|
+
* the same time. Consumers should already be importing from the feature entry.
|
|
2812
|
+
* @since 0.5.0
|
|
2970
2813
|
*/
|
|
2971
2814
|
class BaseGridEditor {
|
|
2972
2815
|
elementRef = inject(ElementRef);
|
|
@@ -3269,6 +3112,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
3269
3112
|
*
|
|
3270
3113
|
* @typeParam TRow - The row data type
|
|
3271
3114
|
* @typeParam TValue - The cell/control value type
|
|
3115
|
+
*
|
|
3116
|
+
* MOVE-IN-V2: this class will physically move into
|
|
3117
|
+
* `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
|
|
3118
|
+
* re-export from the main `@toolbox-web/grid-angular` entry will be removed at
|
|
3119
|
+
* the same time. Consumers should already be importing from the feature entry.
|
|
3120
|
+
* @since 0.13.0
|
|
3272
3121
|
*/
|
|
3273
3122
|
class BaseGridEditorCVA extends BaseGridEditor {
|
|
3274
3123
|
// ============================================================================
|
|
@@ -3532,6 +3381,13 @@ let anchorCounter = 0;
|
|
|
3532
3381
|
*
|
|
3533
3382
|
* @typeParam TRow - The row data type
|
|
3534
3383
|
* @typeParam TValue - The cell value type
|
|
3384
|
+
*
|
|
3385
|
+
* MOVE-IN-V2: this class (and its companion `OverlayPosition` type) will
|
|
3386
|
+
* physically move into `@toolbox-web/grid-angular/features/editing` in v2.0.0;
|
|
3387
|
+
* the deprecated re-export from the main `@toolbox-web/grid-angular` entry
|
|
3388
|
+
* will be removed at the same time. Consumers should already be importing
|
|
3389
|
+
* from the feature entry.
|
|
3390
|
+
* @since 0.13.0
|
|
3535
3391
|
*/
|
|
3536
3392
|
class BaseOverlayEditor extends BaseGridEditor {
|
|
3537
3393
|
_elementRef = inject(ElementRef);
|
|
@@ -3998,6 +3854,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
3998
3854
|
* ```
|
|
3999
3855
|
*
|
|
4000
3856
|
* @category Directive
|
|
3857
|
+
* @since 0.13.0
|
|
4001
3858
|
*/
|
|
4002
3859
|
class TbwGridColumn {
|
|
4003
3860
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridColumn, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -4010,6 +3867,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4010
3867
|
}]
|
|
4011
3868
|
}] });
|
|
4012
3869
|
|
|
3870
|
+
// Global registry mapping DOM elements to their templates
|
|
3871
|
+
const detailTemplateRegistry = new Map();
|
|
3872
|
+
/**
|
|
3873
|
+
* Gets the detail template registered for a given grid element.
|
|
3874
|
+
* Used by AngularGridAdapter to retrieve templates at render time.
|
|
3875
|
+
* @since 0.1.0
|
|
3876
|
+
*/
|
|
3877
|
+
function getDetailTemplate(gridElement) {
|
|
3878
|
+
// Look for tbw-grid-detail child and get its template
|
|
3879
|
+
const detailElement = gridElement.querySelector('tbw-grid-detail');
|
|
3880
|
+
if (detailElement) {
|
|
3881
|
+
return detailTemplateRegistry.get(detailElement);
|
|
3882
|
+
}
|
|
3883
|
+
return undefined;
|
|
3884
|
+
}
|
|
3885
|
+
/**
|
|
3886
|
+
* Directive that captures an `<ng-template>` for use as a master-detail row renderer.
|
|
3887
|
+
*
|
|
3888
|
+
* This enables declarative Angular component usage for expandable detail rows
|
|
3889
|
+
* that appear below the main row when expanded.
|
|
3890
|
+
*
|
|
3891
|
+
* ## Usage
|
|
3892
|
+
*
|
|
3893
|
+
* ```html
|
|
3894
|
+
* <tbw-grid [rows]="rows" [gridConfig]="config">
|
|
3895
|
+
* <tbw-grid-detail [showExpandColumn]="true" animation="slide">
|
|
3896
|
+
* <ng-template let-row>
|
|
3897
|
+
* <app-detail-panel [employee]="row" />
|
|
3898
|
+
* </ng-template>
|
|
3899
|
+
* </tbw-grid-detail>
|
|
3900
|
+
* </tbw-grid>
|
|
3901
|
+
* ```
|
|
3902
|
+
*
|
|
3903
|
+
* The template context provides:
|
|
3904
|
+
* - `$implicit` / `row`: The full row data object
|
|
3905
|
+
*
|
|
3906
|
+
* Import the directive from the master-detail feature entry:
|
|
3907
|
+
*
|
|
3908
|
+
* ```typescript
|
|
3909
|
+
* import { GridDetailView } from '@toolbox-web/grid-angular/features/master-detail';
|
|
3910
|
+
*
|
|
3911
|
+
* @Component({
|
|
3912
|
+
* imports: [GridDetailView],
|
|
3913
|
+
* // ...
|
|
3914
|
+
* })
|
|
3915
|
+
* ```
|
|
3916
|
+
*
|
|
3917
|
+
* > Note: `GridDetailView` is also re-exported from `@toolbox-web/grid-angular`
|
|
3918
|
+
* > for backwards compatibility, but that re-export is deprecated and will be
|
|
3919
|
+
* > removed in v2.0.0. Always import from the feature entry.
|
|
3920
|
+
*
|
|
3921
|
+
* @example
|
|
3922
|
+
* ```html
|
|
3923
|
+
* <tbw-grid [rows]="rows" [gridConfig]="config">
|
|
3924
|
+
* <tbw-grid-detail [showExpandColumn]="true" animation="slide">
|
|
3925
|
+
* <ng-template let-row>
|
|
3926
|
+
* <app-detail-panel [employee]="row" />
|
|
3927
|
+
* </ng-template>
|
|
3928
|
+
* </tbw-grid-detail>
|
|
3929
|
+
* </tbw-grid>
|
|
3930
|
+
* ```
|
|
3931
|
+
*
|
|
3932
|
+
* @category Directive
|
|
3933
|
+
* @since 0.1.0
|
|
3934
|
+
*/
|
|
3935
|
+
class GridDetailView {
|
|
3936
|
+
elementRef = inject((ElementRef));
|
|
3937
|
+
/** Whether to show the expand/collapse column. Default: true */
|
|
3938
|
+
showExpandColumn = input(true, ...(ngDevMode ? [{ debugName: "showExpandColumn" }] : /* istanbul ignore next */ []));
|
|
3939
|
+
/** Animation style for expand/collapse. Default: 'slide' */
|
|
3940
|
+
animation = input('slide', ...(ngDevMode ? [{ debugName: "animation" }] : /* istanbul ignore next */ []));
|
|
3941
|
+
/**
|
|
3942
|
+
* Query for the ng-template content child.
|
|
3943
|
+
*/
|
|
3944
|
+
template = contentChild((TemplateRef), ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
|
|
3945
|
+
/** Effect that triggers when the template is available */
|
|
3946
|
+
onTemplateReceived = effect(() => {
|
|
3947
|
+
const template = this.template();
|
|
3948
|
+
if (template) {
|
|
3949
|
+
// Register the template for this element
|
|
3950
|
+
detailTemplateRegistry.set(this.elementRef.nativeElement, template);
|
|
3951
|
+
}
|
|
3952
|
+
}, ...(ngDevMode ? [{ debugName: "onTemplateReceived" }] : /* istanbul ignore next */ []));
|
|
3953
|
+
/**
|
|
3954
|
+
* Static type guard for template context.
|
|
3955
|
+
* Enables type inference in templates.
|
|
3956
|
+
*/
|
|
3957
|
+
static ngTemplateContextGuard(dir, ctx) {
|
|
3958
|
+
return true;
|
|
3959
|
+
}
|
|
3960
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridDetailView, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3961
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.5", type: GridDetailView, isStandalone: true, selector: "tbw-grid-detail", inputs: { showExpandColumn: { classPropertyName: "showExpandColumn", publicName: "showExpandColumn", isSignal: true, isRequired: false, transformFunction: null }, animation: { classPropertyName: "animation", publicName: "animation", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "template", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], ngImport: i0 });
|
|
3962
|
+
}
|
|
3963
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridDetailView, decorators: [{
|
|
3964
|
+
type: Directive,
|
|
3965
|
+
args: [{ selector: 'tbw-grid-detail' }]
|
|
3966
|
+
}], propDecorators: { showExpandColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExpandColumn", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
3967
|
+
|
|
4013
3968
|
/**
|
|
4014
3969
|
* Directive that registers `<tbw-grid-header>` as a known Angular element.
|
|
4015
3970
|
*
|
|
@@ -4036,6 +3991,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4036
3991
|
* ```
|
|
4037
3992
|
*
|
|
4038
3993
|
* @category Directive
|
|
3994
|
+
* @since 0.13.0
|
|
4039
3995
|
*/
|
|
4040
3996
|
class TbwGridHeader {
|
|
4041
3997
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -4053,6 +4009,7 @@ const FORM_ARRAY_CONTEXT = Symbol('formArrayContext');
|
|
|
4053
4009
|
/**
|
|
4054
4010
|
* Gets the FormArrayContext from a grid element, if present.
|
|
4055
4011
|
* @internal
|
|
4012
|
+
* @since 0.11.0
|
|
4056
4013
|
*/
|
|
4057
4014
|
function getLazyFormContext(gridElement) {
|
|
4058
4015
|
return gridElement[FORM_ARRAY_CONTEXT];
|
|
@@ -4132,6 +4089,14 @@ function getLazyFormContext(gridElement) {
|
|
|
4132
4089
|
*
|
|
4133
4090
|
* @see GridFormArray For small datasets with full upfront validation
|
|
4134
4091
|
* @category Directive
|
|
4092
|
+
*
|
|
4093
|
+
* MOVE-IN-V2: this directive (and its `LazyFormFactory`, `RowFormChangeEvent`
|
|
4094
|
+
* types and `getLazyFormContext` helper) will physically move into
|
|
4095
|
+
* `@toolbox-web/grid-angular/features/editing` in v2.0.0; the deprecated
|
|
4096
|
+
* re-exports from the main `@toolbox-web/grid-angular` entry will be removed
|
|
4097
|
+
* at the same time. Consumers should already be importing from the feature
|
|
4098
|
+
* entry.
|
|
4099
|
+
* @since 0.11.0
|
|
4135
4100
|
*/
|
|
4136
4101
|
class GridLazyForm {
|
|
4137
4102
|
elementRef = inject((ElementRef));
|
|
@@ -4517,15 +4482,121 @@ class GridLazyForm {
|
|
|
4517
4482
|
}
|
|
4518
4483
|
return true;
|
|
4519
4484
|
}
|
|
4520
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridLazyForm, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
4521
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: GridLazyForm, isStandalone: true, selector: "tbw-grid[lazyForm]", inputs: { lazyForm: { classPropertyName: "lazyForm", publicName: "lazyForm", isSignal: true, isRequired: true, transformFunction: null }, syncValidation: { classPropertyName: "syncValidation", publicName: "syncValidation", isSignal: true, isRequired: false, transformFunction: null }, keepFormGroups: { classPropertyName: "keepFormGroups", publicName: "keepFormGroups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowFormChange: "rowFormChange" }, ngImport: i0 });
|
|
4485
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridLazyForm, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
4486
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: GridLazyForm, isStandalone: true, selector: "tbw-grid[lazyForm]", inputs: { lazyForm: { classPropertyName: "lazyForm", publicName: "lazyForm", isSignal: true, isRequired: true, transformFunction: null }, syncValidation: { classPropertyName: "syncValidation", publicName: "syncValidation", isSignal: true, isRequired: false, transformFunction: null }, keepFormGroups: { classPropertyName: "keepFormGroups", publicName: "keepFormGroups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowFormChange: "rowFormChange" }, ngImport: i0 });
|
|
4487
|
+
}
|
|
4488
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridLazyForm, decorators: [{
|
|
4489
|
+
type: Directive,
|
|
4490
|
+
args: [{
|
|
4491
|
+
selector: 'tbw-grid[lazyForm]',
|
|
4492
|
+
}]
|
|
4493
|
+
}], propDecorators: { lazyForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyForm", required: true }] }], syncValidation: [{ type: i0.Input, args: [{ isSignal: true, alias: "syncValidation", required: false }] }], keepFormGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepFormGroups", required: false }] }], rowFormChange: [{ type: i0.Output, args: ["rowFormChange"] }] } });
|
|
4494
|
+
|
|
4495
|
+
/**
|
|
4496
|
+
* Registry to store responsive card templates by grid element.
|
|
4497
|
+
* Used by AngularGridAdapter to create card renderers.
|
|
4498
|
+
*/
|
|
4499
|
+
const responsiveCardTemplateRegistry = new Map();
|
|
4500
|
+
/**
|
|
4501
|
+
* Retrieves the responsive card template for a grid element.
|
|
4502
|
+
*
|
|
4503
|
+
* @param gridElement - The grid element to look up
|
|
4504
|
+
* @returns The template reference or undefined if not found
|
|
4505
|
+
* @since 0.4.0
|
|
4506
|
+
*/
|
|
4507
|
+
function getResponsiveCardTemplate(gridElement) {
|
|
4508
|
+
// Find the tbw-grid-responsive-card element inside the grid
|
|
4509
|
+
const cardElement = gridElement.querySelector('tbw-grid-responsive-card');
|
|
4510
|
+
if (!cardElement)
|
|
4511
|
+
return undefined;
|
|
4512
|
+
return responsiveCardTemplateRegistry.get(cardElement);
|
|
4513
|
+
}
|
|
4514
|
+
/**
|
|
4515
|
+
* Directive for providing custom Angular templates for responsive card layout.
|
|
4516
|
+
*
|
|
4517
|
+
* Use this directive to define how each row should render when the grid
|
|
4518
|
+
* is in responsive/mobile mode. The template receives the row data and index.
|
|
4519
|
+
*
|
|
4520
|
+
* ## Usage
|
|
4521
|
+
*
|
|
4522
|
+
* ```html
|
|
4523
|
+
* <tbw-grid [rows]="employees">
|
|
4524
|
+
* <tbw-grid-responsive-card>
|
|
4525
|
+
* <ng-template let-employee let-idx="index">
|
|
4526
|
+
* <div class="employee-card">
|
|
4527
|
+
* <img [src]="employee.avatar" alt="">
|
|
4528
|
+
* <div class="info">
|
|
4529
|
+
* <strong>{{ employee.name }}</strong>
|
|
4530
|
+
* <span>{{ employee.department }}</span>
|
|
4531
|
+
* </div>
|
|
4532
|
+
* </div>
|
|
4533
|
+
* </ng-template>
|
|
4534
|
+
* </tbw-grid-responsive-card>
|
|
4535
|
+
* </tbw-grid>
|
|
4536
|
+
* ```
|
|
4537
|
+
*
|
|
4538
|
+
* ## Important Notes
|
|
4539
|
+
*
|
|
4540
|
+
* - The ResponsivePlugin must be added to your grid config
|
|
4541
|
+
* - The Grid directive will automatically configure the plugin's cardRenderer
|
|
4542
|
+
* - Template context provides `$implicit` (row), `row`, and `index`
|
|
4543
|
+
*
|
|
4544
|
+
* @see ResponsivePlugin
|
|
4545
|
+
* @category Directive
|
|
4546
|
+
* @since 0.4.0
|
|
4547
|
+
*/
|
|
4548
|
+
class GridResponsiveCard {
|
|
4549
|
+
elementRef = inject((ElementRef));
|
|
4550
|
+
/**
|
|
4551
|
+
* Card row height in pixels. Use `'auto'` for dynamic height based on content.
|
|
4552
|
+
*
|
|
4553
|
+
* Mirrors to the `card-row-height` attribute on the underlying
|
|
4554
|
+
* `<tbw-grid-responsive-card>` element which the ResponsivePlugin reads.
|
|
4555
|
+
*
|
|
4556
|
+
* @default 'auto'
|
|
4557
|
+
*/
|
|
4558
|
+
cardRowHeight = input(...(ngDevMode ? [undefined, { debugName: "cardRowHeight" }] : /* istanbul ignore next */ []));
|
|
4559
|
+
/**
|
|
4560
|
+
* The ng-template containing the card content.
|
|
4561
|
+
*/
|
|
4562
|
+
template = contentChild((TemplateRef), ...(ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []));
|
|
4563
|
+
/**
|
|
4564
|
+
* Effect that registers the template when it becomes available.
|
|
4565
|
+
*/
|
|
4566
|
+
onTemplateReceived = effect(() => {
|
|
4567
|
+
const template = this.template();
|
|
4568
|
+
if (template) {
|
|
4569
|
+
responsiveCardTemplateRegistry.set(this.elementRef.nativeElement, template);
|
|
4570
|
+
}
|
|
4571
|
+
}, ...(ngDevMode ? [{ debugName: "onTemplateReceived" }] : /* istanbul ignore next */ []));
|
|
4572
|
+
/**
|
|
4573
|
+
* Effect that mirrors the `cardRowHeight` input to the kebab-cased attribute
|
|
4574
|
+
* read by the ResponsivePlugin.
|
|
4575
|
+
*/
|
|
4576
|
+
onCardRowHeightChange = effect(() => {
|
|
4577
|
+
const value = this.cardRowHeight();
|
|
4578
|
+
const element = this.elementRef.nativeElement;
|
|
4579
|
+
if (value === undefined) {
|
|
4580
|
+
element.removeAttribute('card-row-height');
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4583
|
+
element.setAttribute('card-row-height', value === 'auto' ? 'auto' : String(value));
|
|
4584
|
+
}, ...(ngDevMode ? [{ debugName: "onCardRowHeightChange" }] : /* istanbul ignore next */ []));
|
|
4585
|
+
/**
|
|
4586
|
+
* Type guard for template context inference.
|
|
4587
|
+
*/
|
|
4588
|
+
static ngTemplateContextGuard(_directive, context) {
|
|
4589
|
+
return true;
|
|
4590
|
+
}
|
|
4591
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridResponsiveCard, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
4592
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.5", type: GridResponsiveCard, isStandalone: true, selector: "tbw-grid-responsive-card", inputs: { cardRowHeight: { classPropertyName: "cardRowHeight", publicName: "cardRowHeight", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "template", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], ngImport: i0 });
|
|
4522
4593
|
}
|
|
4523
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type:
|
|
4594
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: GridResponsiveCard, decorators: [{
|
|
4524
4595
|
type: Directive,
|
|
4525
4596
|
args: [{
|
|
4526
|
-
selector: 'tbw-grid
|
|
4597
|
+
selector: 'tbw-grid-responsive-card',
|
|
4527
4598
|
}]
|
|
4528
|
-
}], propDecorators: {
|
|
4599
|
+
}], propDecorators: { cardRowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardRowHeight", required: false }] }], template: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
4529
4600
|
|
|
4530
4601
|
/**
|
|
4531
4602
|
* Directive that registers `<tbw-grid-tool-buttons>` as a known Angular element.
|
|
@@ -4554,6 +4625,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4554
4625
|
* ```
|
|
4555
4626
|
*
|
|
4556
4627
|
* @category Directive
|
|
4628
|
+
* @since 0.13.0
|
|
4557
4629
|
*/
|
|
4558
4630
|
class TbwGridToolButtons {
|
|
4559
4631
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TbwGridToolButtons, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -4566,6 +4638,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4566
4638
|
}]
|
|
4567
4639
|
}] });
|
|
4568
4640
|
|
|
4641
|
+
/** Capitalize the first letter of a string for header generation. */
|
|
4642
|
+
function capitalize(str) {
|
|
4643
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
4644
|
+
}
|
|
4645
|
+
/**
|
|
4646
|
+
* Generate a human-readable header from a field name.
|
|
4647
|
+
*
|
|
4648
|
+
* Handles camelCase, snake_case, and kebab-case.
|
|
4649
|
+
*
|
|
4650
|
+
* @example
|
|
4651
|
+
* generateHeader('firstName') → 'First Name'
|
|
4652
|
+
* generateHeader('last_name') → 'Last Name'
|
|
4653
|
+
* generateHeader('email-address') → 'Email Address'
|
|
4654
|
+
* generateHeader('id') → 'ID' (special case)
|
|
4655
|
+
*/
|
|
4656
|
+
function generateHeader(field) {
|
|
4657
|
+
if (field.toLowerCase() === 'id')
|
|
4658
|
+
return 'ID';
|
|
4659
|
+
const words = field
|
|
4660
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
4661
|
+
.replace(/[_-]/g, ' ')
|
|
4662
|
+
.split(' ')
|
|
4663
|
+
.filter(Boolean);
|
|
4664
|
+
return words.map(capitalize).join(' ');
|
|
4665
|
+
}
|
|
4666
|
+
/** Valid column types from the shorthand notation. */
|
|
4667
|
+
const VALID_TYPES = new Set(['string', 'number', 'boolean', 'date', 'datetime', 'currency']);
|
|
4668
|
+
/**
|
|
4669
|
+
* Parse a column shorthand string into a ColumnConfig.
|
|
4670
|
+
*
|
|
4671
|
+
* Supports formats:
|
|
4672
|
+
* - `'fieldName'` → `{ field: 'fieldName', header: 'Field Name' }`
|
|
4673
|
+
* - `'fieldName:type'` → `{ field: 'fieldName', header: 'Field Name', type: 'type' }`
|
|
4674
|
+
*
|
|
4675
|
+
* @param shorthand - The shorthand string (e.g., 'name', 'salary:number')
|
|
4676
|
+
* @returns A ColumnConfig object
|
|
4677
|
+
* @since 1.4.0
|
|
4678
|
+
*/
|
|
4679
|
+
function parseColumnShorthand(shorthand) {
|
|
4680
|
+
const colonIndex = shorthand.lastIndexOf(':');
|
|
4681
|
+
if (colonIndex > 0) {
|
|
4682
|
+
const potentialType = shorthand.slice(colonIndex + 1).toLowerCase();
|
|
4683
|
+
if (VALID_TYPES.has(potentialType)) {
|
|
4684
|
+
const field = shorthand.slice(0, colonIndex);
|
|
4685
|
+
return {
|
|
4686
|
+
field: field,
|
|
4687
|
+
header: generateHeader(field),
|
|
4688
|
+
type: potentialType,
|
|
4689
|
+
};
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
return {
|
|
4693
|
+
field: shorthand,
|
|
4694
|
+
header: generateHeader(shorthand),
|
|
4695
|
+
};
|
|
4696
|
+
}
|
|
4697
|
+
/**
|
|
4698
|
+
* Normalize an array of column shorthands to ColumnConfig objects.
|
|
4699
|
+
*
|
|
4700
|
+
* @param columns - Array of column shorthands (strings or ColumnConfig objects)
|
|
4701
|
+
* @returns Array of ColumnConfig objects
|
|
4702
|
+
* @since 1.4.0
|
|
4703
|
+
*/
|
|
4704
|
+
function normalizeColumns(columns) {
|
|
4705
|
+
return columns.map((col) => (typeof col === 'string' ? parseColumnShorthand(col) : col));
|
|
4706
|
+
}
|
|
4707
|
+
/**
|
|
4708
|
+
* Apply column defaults to a list of columns. Individual column properties
|
|
4709
|
+
* override defaults.
|
|
4710
|
+
* @since 1.4.0
|
|
4711
|
+
*/
|
|
4712
|
+
function applyColumnDefaults(columns, defaults) {
|
|
4713
|
+
if (!defaults)
|
|
4714
|
+
return columns;
|
|
4715
|
+
return columns.map((col) => ({ ...defaults, ...col }));
|
|
4716
|
+
}
|
|
4717
|
+
/** Check if an array of columns contains any shorthand strings. * @since 1.4.0
|
|
4718
|
+
*/
|
|
4719
|
+
function hasColumnShorthands(columns) {
|
|
4720
|
+
return columns.some((col) => typeof col === 'string');
|
|
4721
|
+
}
|
|
4722
|
+
|
|
4723
|
+
/** Per-element map of claimed feature names → config getter. */
|
|
4724
|
+
const featureClaims = new WeakMap();
|
|
4725
|
+
/** Per-element set of claimed event names (matches `keyof DataGridEventMap`). */
|
|
4726
|
+
const eventClaims = new WeakMap();
|
|
4727
|
+
/**
|
|
4728
|
+
* Register a feature claim. Called by a feature directive's constructor;
|
|
4729
|
+
* the {@link Grid} directive will then use {@link getFeatureClaim} during
|
|
4730
|
+
* plugin creation instead of reading its own deprecated input.
|
|
4731
|
+
* @internal
|
|
4732
|
+
* @since 1.4.0
|
|
4733
|
+
*/
|
|
4734
|
+
function registerFeatureClaim(grid, name, getConfig) {
|
|
4735
|
+
let map = featureClaims.get(grid);
|
|
4736
|
+
if (!map) {
|
|
4737
|
+
map = new Map();
|
|
4738
|
+
featureClaims.set(grid, map);
|
|
4739
|
+
}
|
|
4740
|
+
map.set(name, getConfig);
|
|
4741
|
+
}
|
|
4742
|
+
/**
|
|
4743
|
+
* Look up a feature claim. Returns the registered config getter, or
|
|
4744
|
+
* `undefined` if no directive owns this feature on this element.
|
|
4745
|
+
* @internal
|
|
4746
|
+
* @since 1.4.0
|
|
4747
|
+
*/
|
|
4748
|
+
function getFeatureClaim(grid, name) {
|
|
4749
|
+
return featureClaims.get(grid)?.get(name);
|
|
4750
|
+
}
|
|
4751
|
+
/**
|
|
4752
|
+
* Drop a feature claim. Called by a feature directive's `ngOnDestroy` so
|
|
4753
|
+
* that, if the directive is removed (e.g. via `*ngIf`) but the host
|
|
4754
|
+
* `<tbw-grid>` survives, {@link Grid}'s deprecated input takes back over.
|
|
4755
|
+
* @internal
|
|
4756
|
+
* @since 1.4.0
|
|
4757
|
+
*/
|
|
4758
|
+
function unregisterFeatureClaim(grid, name) {
|
|
4759
|
+
featureClaims.get(grid)?.delete(name);
|
|
4760
|
+
}
|
|
4761
|
+
/**
|
|
4762
|
+
* Mark an event as owned by a feature directive. {@link Grid}'s
|
|
4763
|
+
* `setupEventListeners` skips wiring its own deprecated `output()` for any
|
|
4764
|
+
* claimed event — the directive owns the listener and the emit.
|
|
4765
|
+
* @internal
|
|
4766
|
+
* @since 1.4.0
|
|
4767
|
+
*/
|
|
4768
|
+
function claimEvent(grid, eventName) {
|
|
4769
|
+
let set = eventClaims.get(grid);
|
|
4770
|
+
if (!set) {
|
|
4771
|
+
set = new Set();
|
|
4772
|
+
eventClaims.set(grid, set);
|
|
4773
|
+
}
|
|
4774
|
+
set.add(eventName);
|
|
4775
|
+
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Returns true if a directive has claimed this event on this grid element.
|
|
4778
|
+
* @internal
|
|
4779
|
+
* @since 1.4.0
|
|
4780
|
+
*/
|
|
4781
|
+
function isEventClaimed(grid, eventName) {
|
|
4782
|
+
return eventClaims.get(grid)?.has(eventName) ?? false;
|
|
4783
|
+
}
|
|
4784
|
+
/**
|
|
4785
|
+
* Drop an event claim. Pair with {@link claimEvent} in a directive's
|
|
4786
|
+
* `ngOnDestroy`.
|
|
4787
|
+
* @internal
|
|
4788
|
+
* @since 1.4.0
|
|
4789
|
+
*/
|
|
4790
|
+
function unclaimEvent(grid, eventName) {
|
|
4791
|
+
eventClaims.get(grid)?.delete(eventName);
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4569
4794
|
/**
|
|
4570
4795
|
* Directive that automatically registers the Angular adapter with tbw-grid elements.
|
|
4571
4796
|
*
|
|
@@ -4601,6 +4826,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4601
4826
|
* - Handles cleanup on destruction
|
|
4602
4827
|
*
|
|
4603
4828
|
* @category Directive
|
|
4829
|
+
* @since 0.1.0
|
|
4604
4830
|
*/
|
|
4605
4831
|
class Grid {
|
|
4606
4832
|
elementRef = inject((ElementRef));
|
|
@@ -4683,13 +4909,25 @@ class Grid {
|
|
|
4683
4909
|
if (columnsValue === undefined)
|
|
4684
4910
|
return;
|
|
4685
4911
|
const grid = this.elementRef.nativeElement;
|
|
4912
|
+
// First normalize any shorthand strings to ColumnConfig objects, then
|
|
4913
|
+
// merge in any per-grid column defaults. Individual column props always win.
|
|
4914
|
+
// Note: Angular ColumnConfig allows component classes for renderer/editor,
|
|
4915
|
+
// which the adapter normalizes via processColumn below; we widen to `any`
|
|
4916
|
+
// here so the shorthand helpers (typed against the core ColumnConfig) accept
|
|
4917
|
+
// the Angular-flavoured payload unchanged.
|
|
4918
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4919
|
+
const normalized = applyColumnDefaults(
|
|
4920
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4921
|
+
normalizeColumns(columnsValue),
|
|
4922
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4923
|
+
this.columnDefaults());
|
|
4686
4924
|
// Process columns through the adapter to convert Angular component classes
|
|
4687
4925
|
// (renderer/editor) to functions — the grid's columns setter does NOT call
|
|
4688
4926
|
// processConfig, unlike gridConfig. Without this, raw component classes
|
|
4689
4927
|
// would be invoked without `new`, causing runtime errors.
|
|
4690
4928
|
const processed = this.adapter
|
|
4691
|
-
?
|
|
4692
|
-
:
|
|
4929
|
+
? normalized.map((col) => this.adapter.processColumn(col))
|
|
4930
|
+
: normalized;
|
|
4693
4931
|
grid.columns = processed;
|
|
4694
4932
|
});
|
|
4695
4933
|
// Effect to sync fitMode to the grid element
|
|
@@ -4824,21 +5062,35 @@ class Grid {
|
|
|
4824
5062
|
/**
|
|
4825
5063
|
* Column configuration array.
|
|
4826
5064
|
*
|
|
5065
|
+
* Accepts either full `ColumnConfig` objects or shorthand strings such as
|
|
5066
|
+
* `'name'` or `'salary:number'`. Shorthands auto-generate human-readable
|
|
5067
|
+
* headers from the field name.
|
|
5068
|
+
*
|
|
4827
5069
|
* Shorthand for setting columns without wrapping them in a full `gridConfig`.
|
|
4828
5070
|
* If both `columns` and `gridConfig.columns` are set, `columns` takes precedence
|
|
4829
5071
|
* (see configuration precedence system).
|
|
4830
5072
|
*
|
|
4831
5073
|
* @example
|
|
4832
5074
|
* ```html
|
|
4833
|
-
* <tbw-grid [rows]="data" [columns]="[
|
|
4834
|
-
* { field: 'id', header: 'ID', pinned: 'left', width: 80 },
|
|
4835
|
-
* { field: 'name', header: 'Name' },
|
|
4836
|
-
* { field: 'email', header: 'Email' }
|
|
4837
|
-
* ]" />
|
|
5075
|
+
* <tbw-grid [rows]="data" [columns]="['id:number', 'name', { field: 'status', editable: true }]" />
|
|
4838
5076
|
* ```
|
|
4839
5077
|
*/
|
|
4840
5078
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4841
5079
|
columns = input(...(ngDevMode ? [undefined, { debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
5080
|
+
/**
|
|
5081
|
+
* Default column properties applied to every column in `columns`.
|
|
5082
|
+
* Individual column properties override these defaults.
|
|
5083
|
+
*
|
|
5084
|
+
* @example
|
|
5085
|
+
* ```html
|
|
5086
|
+
* <tbw-grid
|
|
5087
|
+
* [columnDefaults]="{ sortable: true, resizable: true }"
|
|
5088
|
+
* [columns]="[{ field: 'id', sortable: false }, { field: 'name' }]"
|
|
5089
|
+
* />
|
|
5090
|
+
* ```
|
|
5091
|
+
*/
|
|
5092
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5093
|
+
columnDefaults = input(...(ngDevMode ? [undefined, { debugName: "columnDefaults" }] : /* istanbul ignore next */ []));
|
|
4842
5094
|
/**
|
|
4843
5095
|
* Column sizing strategy.
|
|
4844
5096
|
*
|
|
@@ -4912,6 +5164,9 @@ class Grid {
|
|
|
4912
5164
|
* <!-- Full config object -->
|
|
4913
5165
|
* <tbw-grid [selection]="{ mode: 'range', checkbox: true }" />
|
|
4914
5166
|
* ```
|
|
5167
|
+
*
|
|
5168
|
+
* @deprecated Use `GridSelectionDirective` from
|
|
5169
|
+
* `@toolbox-web/grid-angular/features/selection`. Will be removed in v2.0.0.
|
|
4915
5170
|
*/
|
|
4916
5171
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4917
5172
|
selection = input(...(ngDevMode ? [undefined, { debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
@@ -4936,6 +5191,9 @@ class Grid {
|
|
|
4936
5191
|
* <!-- Full config with callbacks -->
|
|
4937
5192
|
* <tbw-grid [editing]="{ editOn: 'dblclick', onBeforeEditClose: myCallback }" />
|
|
4938
5193
|
* ```
|
|
5194
|
+
*
|
|
5195
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5196
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
4939
5197
|
*/
|
|
4940
5198
|
editing = input(...(ngDevMode ? [undefined, { debugName: "editing" }] : /* istanbul ignore next */ []));
|
|
4941
5199
|
/**
|
|
@@ -4950,6 +5208,9 @@ class Grid {
|
|
|
4950
5208
|
* ```html
|
|
4951
5209
|
* <tbw-grid [selection]="'range'" [clipboard]="true" />
|
|
4952
5210
|
* ```
|
|
5211
|
+
*
|
|
5212
|
+
* @deprecated Use `GridClipboardDirective` from
|
|
5213
|
+
* `@toolbox-web/grid-angular/features/clipboard`. Will be removed in v2.0.0.
|
|
4953
5214
|
*/
|
|
4954
5215
|
clipboard = input(...(ngDevMode ? [undefined, { debugName: "clipboard" }] : /* istanbul ignore next */ []));
|
|
4955
5216
|
/**
|
|
@@ -4964,6 +5225,9 @@ class Grid {
|
|
|
4964
5225
|
* ```html
|
|
4965
5226
|
* <tbw-grid [contextMenu]="true" />
|
|
4966
5227
|
* ```
|
|
5228
|
+
*
|
|
5229
|
+
* @deprecated Use `GridContextMenuDirective` from
|
|
5230
|
+
* `@toolbox-web/grid-angular/features/context-menu`. Will be removed in v2.0.0.
|
|
4967
5231
|
*/
|
|
4968
5232
|
contextMenu = input(...(ngDevMode ? [undefined, { debugName: "contextMenu" }] : /* istanbul ignore next */ []));
|
|
4969
5233
|
/**
|
|
@@ -4988,6 +5252,9 @@ class Grid {
|
|
|
4988
5252
|
* <!-- Full config -->
|
|
4989
5253
|
* <tbw-grid [multiSort]="{ maxSortColumns: 3 }" />
|
|
4990
5254
|
* ```
|
|
5255
|
+
*
|
|
5256
|
+
* @deprecated Use `GridMultiSortDirective` from
|
|
5257
|
+
* `@toolbox-web/grid-angular/features/multi-sort`. Will be removed in v2.0.0.
|
|
4991
5258
|
*/
|
|
4992
5259
|
multiSort = input(...(ngDevMode ? [undefined, { debugName: "multiSort" }] : /* istanbul ignore next */ []));
|
|
4993
5260
|
/**
|
|
@@ -5003,6 +5270,13 @@ class Grid {
|
|
|
5003
5270
|
* <tbw-grid [filtering]="true" />
|
|
5004
5271
|
* <tbw-grid [filtering]="{ debounceMs: 200 }" />
|
|
5005
5272
|
* ```
|
|
5273
|
+
*
|
|
5274
|
+
* @deprecated Use `GridFilteringDirective` from
|
|
5275
|
+
* `@toolbox-web/grid-angular/features/filtering` and add it to your
|
|
5276
|
+
* component's `imports`. The directive owns the `filtering` input + the
|
|
5277
|
+
* `filterChange` output and lets the typed surface tree-shake away when
|
|
5278
|
+
* the feature is not imported. This input remains as a non-breaking shim
|
|
5279
|
+
* and will be removed in v2.0.0.
|
|
5006
5280
|
*/
|
|
5007
5281
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5008
5282
|
filtering = input(...(ngDevMode ? [undefined, { debugName: "filtering" }] : /* istanbul ignore next */ []));
|
|
@@ -5018,6 +5292,9 @@ class Grid {
|
|
|
5018
5292
|
* ```html
|
|
5019
5293
|
* <tbw-grid [reorderColumns]="true" />
|
|
5020
5294
|
* ```
|
|
5295
|
+
*
|
|
5296
|
+
* @deprecated Use `GridReorderColumnsDirective` from
|
|
5297
|
+
* `@toolbox-web/grid-angular/features/reorder-columns`. Will be removed in v2.0.0.
|
|
5021
5298
|
*/
|
|
5022
5299
|
reorderColumns = input(...(ngDevMode ? [undefined, { debugName: "reorderColumns" }] : /* istanbul ignore next */ []));
|
|
5023
5300
|
/**
|
|
@@ -5032,6 +5309,9 @@ class Grid {
|
|
|
5032
5309
|
* ```html
|
|
5033
5310
|
* <tbw-grid [visibility]="true" />
|
|
5034
5311
|
* ```
|
|
5312
|
+
*
|
|
5313
|
+
* @deprecated Use `GridVisibilityDirective` from
|
|
5314
|
+
* `@toolbox-web/grid-angular/features/visibility`. Will be removed in v2.0.0.
|
|
5035
5315
|
*/
|
|
5036
5316
|
visibility = input(...(ngDevMode ? [undefined, { debugName: "visibility" }] : /* istanbul ignore next */ []));
|
|
5037
5317
|
/**
|
|
@@ -5051,6 +5331,9 @@ class Grid {
|
|
|
5051
5331
|
* { field: 'actions', pinned: 'right' }
|
|
5052
5332
|
* ]" />
|
|
5053
5333
|
* ```
|
|
5334
|
+
*
|
|
5335
|
+
* @deprecated Use `GridPinnedColumnsDirective` from
|
|
5336
|
+
* `@toolbox-web/grid-angular/features/pinned-columns`. Will be removed in v2.0.0.
|
|
5054
5337
|
*/
|
|
5055
5338
|
pinnedColumns = input(...(ngDevMode ? [undefined, { debugName: "pinnedColumns" }] : /* istanbul ignore next */ []));
|
|
5056
5339
|
/**
|
|
@@ -5065,6 +5348,9 @@ class Grid {
|
|
|
5065
5348
|
* ```html
|
|
5066
5349
|
* <tbw-grid [groupingColumns]="true" />
|
|
5067
5350
|
* ```
|
|
5351
|
+
*
|
|
5352
|
+
* @deprecated Use `GridGroupingColumnsDirective` from
|
|
5353
|
+
* `@toolbox-web/grid-angular/features/grouping-columns`. Will be removed in v2.0.0.
|
|
5068
5354
|
*/
|
|
5069
5355
|
groupingColumns = input(...(ngDevMode ? [undefined, { debugName: "groupingColumns" }] : /* istanbul ignore next */ []));
|
|
5070
5356
|
/**
|
|
@@ -5079,6 +5365,9 @@ class Grid {
|
|
|
5079
5365
|
* ```html
|
|
5080
5366
|
* <tbw-grid [columnVirtualization]="true" />
|
|
5081
5367
|
* ```
|
|
5368
|
+
*
|
|
5369
|
+
* @deprecated Use `GridColumnVirtualizationDirective` from
|
|
5370
|
+
* `@toolbox-web/grid-angular/features/column-virtualization`. Will be removed in v2.0.0.
|
|
5082
5371
|
*/
|
|
5083
5372
|
columnVirtualization = input(...(ngDevMode ? [undefined, { debugName: "columnVirtualization" }] : /* istanbul ignore next */ []));
|
|
5084
5373
|
/**
|
|
@@ -5104,6 +5393,9 @@ class Grid {
|
|
|
5104
5393
|
* ```html
|
|
5105
5394
|
* <tbw-grid [rowDragDrop]="{ dropZone: 'employees', operation: 'move' }" />
|
|
5106
5395
|
* ```
|
|
5396
|
+
*
|
|
5397
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5398
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5107
5399
|
*/
|
|
5108
5400
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5109
5401
|
rowDragDrop = input(...(ngDevMode ? [undefined, { debugName: "rowDragDrop" }] : /* istanbul ignore next */ []));
|
|
@@ -5119,6 +5411,9 @@ class Grid {
|
|
|
5119
5411
|
* ```html
|
|
5120
5412
|
* <tbw-grid [groupingRows]="{ groupBy: ['department'] }" />
|
|
5121
5413
|
* ```
|
|
5414
|
+
*
|
|
5415
|
+
* @deprecated Use `GridGroupingRowsDirective` from
|
|
5416
|
+
* `@toolbox-web/grid-angular/features/grouping-rows`. Will be removed in v2.0.0.
|
|
5122
5417
|
*/
|
|
5123
5418
|
groupingRows = input(...(ngDevMode ? [undefined, { debugName: "groupingRows" }] : /* istanbul ignore next */ []));
|
|
5124
5419
|
/**
|
|
@@ -5133,6 +5428,9 @@ class Grid {
|
|
|
5133
5428
|
* ```html
|
|
5134
5429
|
* <tbw-grid [pinnedRows]="{ bottom: [{ type: 'aggregation' }] }" />
|
|
5135
5430
|
* ```
|
|
5431
|
+
*
|
|
5432
|
+
* @deprecated Use `GridPinnedRowsDirective` from
|
|
5433
|
+
* `@toolbox-web/grid-angular/features/pinned-rows`. Will be removed in v2.0.0.
|
|
5136
5434
|
*/
|
|
5137
5435
|
pinnedRows = input(...(ngDevMode ? [undefined, { debugName: "pinnedRows" }] : /* istanbul ignore next */ []));
|
|
5138
5436
|
/**
|
|
@@ -5147,6 +5445,9 @@ class Grid {
|
|
|
5147
5445
|
* ```html
|
|
5148
5446
|
* <tbw-grid [tree]="{ childrenField: 'children' }" />
|
|
5149
5447
|
* ```
|
|
5448
|
+
*
|
|
5449
|
+
* @deprecated Use `GridTreeDirective` from
|
|
5450
|
+
* `@toolbox-web/grid-angular/features/tree`. Will be removed in v2.0.0.
|
|
5150
5451
|
*/
|
|
5151
5452
|
tree = input(...(ngDevMode ? [undefined, { debugName: "tree" }] : /* istanbul ignore next */ []));
|
|
5152
5453
|
/**
|
|
@@ -5161,6 +5462,9 @@ class Grid {
|
|
|
5161
5462
|
* ```html
|
|
5162
5463
|
* <tbw-grid [masterDetail]="{ detailRenderer: detailFn }" />
|
|
5163
5464
|
* ```
|
|
5465
|
+
*
|
|
5466
|
+
* @deprecated Use `GridMasterDetailDirective` from
|
|
5467
|
+
* `@toolbox-web/grid-angular/features/master-detail`. Will be removed in v2.0.0.
|
|
5164
5468
|
*/
|
|
5165
5469
|
masterDetail = input(...(ngDevMode ? [undefined, { debugName: "masterDetail" }] : /* istanbul ignore next */ []));
|
|
5166
5470
|
/**
|
|
@@ -5175,6 +5479,9 @@ class Grid {
|
|
|
5175
5479
|
* ```html
|
|
5176
5480
|
* <tbw-grid [responsive]="{ breakpoint: 768 }" />
|
|
5177
5481
|
* ```
|
|
5482
|
+
*
|
|
5483
|
+
* @deprecated Use `GridResponsiveDirective` from
|
|
5484
|
+
* `@toolbox-web/grid-angular/features/responsive`. Will be removed in v2.0.0.
|
|
5178
5485
|
*/
|
|
5179
5486
|
responsive = input(...(ngDevMode ? [undefined, { debugName: "responsive" }] : /* istanbul ignore next */ []));
|
|
5180
5487
|
/**
|
|
@@ -5189,6 +5496,9 @@ class Grid {
|
|
|
5189
5496
|
* ```html
|
|
5190
5497
|
* <tbw-grid [editing]="'dblclick'" [undoRedo]="true" />
|
|
5191
5498
|
* ```
|
|
5499
|
+
*
|
|
5500
|
+
* @deprecated Use `GridUndoRedoDirective` from
|
|
5501
|
+
* `@toolbox-web/grid-angular/features/undo-redo`. Will be removed in v2.0.0.
|
|
5192
5502
|
*/
|
|
5193
5503
|
undoRedo = input(...(ngDevMode ? [undefined, { debugName: "undoRedo" }] : /* istanbul ignore next */ []));
|
|
5194
5504
|
/**
|
|
@@ -5204,6 +5514,9 @@ class Grid {
|
|
|
5204
5514
|
* <tbw-grid [export]="true" />
|
|
5205
5515
|
* <tbw-grid [export]="{ filename: 'data.csv' }" />
|
|
5206
5516
|
* ```
|
|
5517
|
+
*
|
|
5518
|
+
* @deprecated Use `GridExportDirective` from
|
|
5519
|
+
* `@toolbox-web/grid-angular/features/export`. Will be removed in v2.0.0.
|
|
5207
5520
|
*/
|
|
5208
5521
|
exportFeature = input(undefined, { ...(ngDevMode ? { debugName: "exportFeature" } : /* istanbul ignore next */ {}), alias: 'export' });
|
|
5209
5522
|
/**
|
|
@@ -5218,6 +5531,9 @@ class Grid {
|
|
|
5218
5531
|
* ```html
|
|
5219
5532
|
* <tbw-grid [print]="true" />
|
|
5220
5533
|
* ```
|
|
5534
|
+
*
|
|
5535
|
+
* @deprecated Use `GridPrintDirective` from
|
|
5536
|
+
* `@toolbox-web/grid-angular/features/print`. Will be removed in v2.0.0.
|
|
5221
5537
|
*/
|
|
5222
5538
|
print = input(...(ngDevMode ? [undefined, { debugName: "print" }] : /* istanbul ignore next */ []));
|
|
5223
5539
|
/**
|
|
@@ -5232,6 +5548,9 @@ class Grid {
|
|
|
5232
5548
|
* ```html
|
|
5233
5549
|
* <tbw-grid [pivot]="{ rowFields: ['category'], valueField: 'sales' }" />
|
|
5234
5550
|
* ```
|
|
5551
|
+
*
|
|
5552
|
+
* @deprecated Use `GridPivotDirective` from
|
|
5553
|
+
* `@toolbox-web/grid-angular/features/pivot`. Will be removed in v2.0.0.
|
|
5235
5554
|
*/
|
|
5236
5555
|
pivot = input(...(ngDevMode ? [undefined, { debugName: "pivot" }] : /* istanbul ignore next */ []));
|
|
5237
5556
|
/**
|
|
@@ -5246,6 +5565,9 @@ class Grid {
|
|
|
5246
5565
|
* ```html
|
|
5247
5566
|
* <tbw-grid [serverSide]="{ dataSource: fetchDataFn }" />
|
|
5248
5567
|
* ```
|
|
5568
|
+
*
|
|
5569
|
+
* @deprecated Use `GridServerSideDirective` from
|
|
5570
|
+
* `@toolbox-web/grid-angular/features/server-side`. Will be removed in v2.0.0.
|
|
5249
5571
|
*/
|
|
5250
5572
|
serverSide = input(...(ngDevMode ? [undefined, { debugName: "serverSide" }] : /* istanbul ignore next */ []));
|
|
5251
5573
|
/**
|
|
@@ -5256,6 +5578,9 @@ class Grid {
|
|
|
5256
5578
|
* <tbw-grid [tooltip]="true" />
|
|
5257
5579
|
* <tbw-grid [tooltip]="{ header: true, cell: false }" />
|
|
5258
5580
|
* ```
|
|
5581
|
+
*
|
|
5582
|
+
* @deprecated Use `GridTooltipDirective` from
|
|
5583
|
+
* `@toolbox-web/grid-angular/features/tooltip`. Will be removed in v2.0.0.
|
|
5259
5584
|
*/
|
|
5260
5585
|
tooltip = input(...(ngDevMode ? [undefined, { debugName: "tooltip" }] : /* istanbul ignore next */ []));
|
|
5261
5586
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -5315,8 +5640,85 @@ class Grid {
|
|
|
5315
5640
|
* console.log(`Changed ${event.field} to ${event.value} in row ${event.rowIndex}`);
|
|
5316
5641
|
* }
|
|
5317
5642
|
* ```
|
|
5643
|
+
*
|
|
5644
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5645
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5318
5646
|
*/
|
|
5319
5647
|
cellCommit = output();
|
|
5648
|
+
/**
|
|
5649
|
+
* Emitted when a cell edit is cancelled (Escape, click outside without
|
|
5650
|
+
* commit, or `editor.cancel()`).
|
|
5651
|
+
*
|
|
5652
|
+
* @example
|
|
5653
|
+
* ```html
|
|
5654
|
+
* <tbw-grid (cellCancel)="onCellCancel($event)">...</tbw-grid>
|
|
5655
|
+
* ```
|
|
5656
|
+
*
|
|
5657
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5658
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5659
|
+
*/
|
|
5660
|
+
cellCancel = output();
|
|
5661
|
+
/**
|
|
5662
|
+
* Emitted when a cell editor opens.
|
|
5663
|
+
*
|
|
5664
|
+
* @example
|
|
5665
|
+
* ```html
|
|
5666
|
+
* <tbw-grid (editOpen)="onEditOpen($event)">...</tbw-grid>
|
|
5667
|
+
* ```
|
|
5668
|
+
*
|
|
5669
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5670
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5671
|
+
*/
|
|
5672
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5673
|
+
editOpen = output();
|
|
5674
|
+
/**
|
|
5675
|
+
* Emitted before an editor closes. Useful for last-chance validation.
|
|
5676
|
+
*
|
|
5677
|
+
* @example
|
|
5678
|
+
* ```html
|
|
5679
|
+
* <tbw-grid (beforeEditClose)="onBeforeEditClose($event)">...</tbw-grid>
|
|
5680
|
+
* ```
|
|
5681
|
+
*
|
|
5682
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5683
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5684
|
+
*/
|
|
5685
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5686
|
+
beforeEditClose = output();
|
|
5687
|
+
/**
|
|
5688
|
+
* Emitted after an editor closes (whether committed or cancelled).
|
|
5689
|
+
*
|
|
5690
|
+
* @example
|
|
5691
|
+
* ```html
|
|
5692
|
+
* <tbw-grid (editClose)="onEditClose($event)">...</tbw-grid>
|
|
5693
|
+
* ```
|
|
5694
|
+
*
|
|
5695
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5696
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5697
|
+
*/
|
|
5698
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5699
|
+
editClose = output();
|
|
5700
|
+
/**
|
|
5701
|
+
* Emitted when the dirty / changed-rows state transitions.
|
|
5702
|
+
*
|
|
5703
|
+
* @example
|
|
5704
|
+
* ```html
|
|
5705
|
+
* <tbw-grid (dirtyChange)="onDirtyChange($event)">...</tbw-grid>
|
|
5706
|
+
* ```
|
|
5707
|
+
*
|
|
5708
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5709
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5710
|
+
*/
|
|
5711
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5712
|
+
dirtyChange = output();
|
|
5713
|
+
/**
|
|
5714
|
+
* Emitted when row data is replaced (e.g. via the `rows` setter).
|
|
5715
|
+
*
|
|
5716
|
+
* @example
|
|
5717
|
+
* ```html
|
|
5718
|
+
* <tbw-grid (dataChange)="onDataChange($event)">...</tbw-grid>
|
|
5719
|
+
* ```
|
|
5720
|
+
*/
|
|
5721
|
+
dataChange = output();
|
|
5320
5722
|
/**
|
|
5321
5723
|
* Emitted when a row's values are committed (bulk/row editing).
|
|
5322
5724
|
* Provides the row data and change tracking information.
|
|
@@ -5325,6 +5727,9 @@ class Grid {
|
|
|
5325
5727
|
* ```html
|
|
5326
5728
|
* <tbw-grid (rowCommit)="onRowCommit($event)">...</tbw-grid>
|
|
5327
5729
|
* ```
|
|
5730
|
+
*
|
|
5731
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5732
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5328
5733
|
*/
|
|
5329
5734
|
rowCommit = output();
|
|
5330
5735
|
/**
|
|
@@ -5334,6 +5739,9 @@ class Grid {
|
|
|
5334
5739
|
* ```html
|
|
5335
5740
|
* <tbw-grid (changedRowsReset)="onChangedRowsReset($event)">...</tbw-grid>
|
|
5336
5741
|
* ```
|
|
5742
|
+
*
|
|
5743
|
+
* @deprecated Use `GridEditingDirective` from
|
|
5744
|
+
* `@toolbox-web/grid-angular/features/editing`. Will be removed in v2.0.0.
|
|
5337
5745
|
*/
|
|
5338
5746
|
changedRowsReset = output();
|
|
5339
5747
|
/**
|
|
@@ -5352,6 +5760,11 @@ class Grid {
|
|
|
5352
5760
|
* ```html
|
|
5353
5761
|
* <tbw-grid (filterChange)="onFilterChange($event)">...</tbw-grid>
|
|
5354
5762
|
* ```
|
|
5763
|
+
*
|
|
5764
|
+
* @deprecated Use `GridFilteringDirective` from
|
|
5765
|
+
* `@toolbox-web/grid-angular/features/filtering` (the directive
|
|
5766
|
+
* declares the `(filterChange)` output). This output remains as a
|
|
5767
|
+
* non-breaking shim and will be removed in v2.0.0.
|
|
5355
5768
|
*/
|
|
5356
5769
|
filterChange = output();
|
|
5357
5770
|
/**
|
|
@@ -5363,6 +5776,15 @@ class Grid {
|
|
|
5363
5776
|
* ```
|
|
5364
5777
|
*/
|
|
5365
5778
|
columnResize = output();
|
|
5779
|
+
/**
|
|
5780
|
+
* Emitted when a column's width is reset (double-click on the resize handle).
|
|
5781
|
+
*
|
|
5782
|
+
* @example
|
|
5783
|
+
* ```html
|
|
5784
|
+
* <tbw-grid (columnResizeReset)="onColumnResizeReset($event)">...</tbw-grid>
|
|
5785
|
+
* ```
|
|
5786
|
+
*/
|
|
5787
|
+
columnResizeReset = output();
|
|
5366
5788
|
/**
|
|
5367
5789
|
* Emitted when a column is moved via drag-and-drop.
|
|
5368
5790
|
*
|
|
@@ -5370,15 +5792,23 @@ class Grid {
|
|
|
5370
5792
|
* ```html
|
|
5371
5793
|
* <tbw-grid (columnMove)="onColumnMove($event)">...</tbw-grid>
|
|
5372
5794
|
* ```
|
|
5795
|
+
*
|
|
5796
|
+
* @deprecated Use `GridReorderColumnsDirective` from
|
|
5797
|
+
* `@toolbox-web/grid-angular/features/reorder-columns`. Will be removed in v2.0.0.
|
|
5373
5798
|
*/
|
|
5374
5799
|
columnMove = output();
|
|
5375
5800
|
/**
|
|
5376
|
-
* Emitted when column visibility
|
|
5801
|
+
* Emitted when a column is shown or hidden — either via the visibility
|
|
5802
|
+
* sidebar, `grid.toggleColumnVisibility(field)`, `grid.setColumnVisible(field, visible)`,
|
|
5803
|
+
* or `grid.showAllColumns()`.
|
|
5377
5804
|
*
|
|
5378
5805
|
* @example
|
|
5379
5806
|
* ```html
|
|
5380
5807
|
* <tbw-grid (columnVisibility)="onColumnVisibility($event)">...</tbw-grid>
|
|
5381
5808
|
* ```
|
|
5809
|
+
*
|
|
5810
|
+
* @deprecated Use `GridVisibilityDirective` from
|
|
5811
|
+
* `@toolbox-web/grid-angular/features/visibility`. Will be removed in v2.0.0.
|
|
5382
5812
|
*/
|
|
5383
5813
|
columnVisibility = output();
|
|
5384
5814
|
/**
|
|
@@ -5397,6 +5827,9 @@ class Grid {
|
|
|
5397
5827
|
* ```html
|
|
5398
5828
|
* <tbw-grid (selectionChange)="onSelectionChange($event)">...</tbw-grid>
|
|
5399
5829
|
* ```
|
|
5830
|
+
*
|
|
5831
|
+
* @deprecated Use `GridSelectionDirective` from
|
|
5832
|
+
* `@toolbox-web/grid-angular/features/selection`. Will be removed in v2.0.0.
|
|
5400
5833
|
*/
|
|
5401
5834
|
selectionChange = output();
|
|
5402
5835
|
/**
|
|
@@ -5406,6 +5839,9 @@ class Grid {
|
|
|
5406
5839
|
* ```html
|
|
5407
5840
|
* <tbw-grid (rowMove)="onRowMove($event)">...</tbw-grid>
|
|
5408
5841
|
* ```
|
|
5842
|
+
*
|
|
5843
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5844
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5409
5845
|
*/
|
|
5410
5846
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5411
5847
|
rowMove = output();
|
|
@@ -5416,23 +5852,35 @@ class Grid {
|
|
|
5416
5852
|
* ```html
|
|
5417
5853
|
* <tbw-grid (rowDragStart)="onRowDragStart($event)">...</tbw-grid>
|
|
5418
5854
|
* ```
|
|
5855
|
+
*
|
|
5856
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5857
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5419
5858
|
*/
|
|
5420
5859
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5421
5860
|
rowDragStart = output();
|
|
5422
5861
|
/**
|
|
5423
5862
|
* Emitted when a row drag ends (after drop or cancel).
|
|
5863
|
+
*
|
|
5864
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5865
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5424
5866
|
*/
|
|
5425
5867
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5426
5868
|
rowDragEnd = output();
|
|
5427
5869
|
/**
|
|
5428
5870
|
* Emitted on the target grid when rows are dropped from another grid.
|
|
5429
5871
|
* Cancelable via `event.preventDefault()`.
|
|
5872
|
+
*
|
|
5873
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5874
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5430
5875
|
*/
|
|
5431
5876
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5432
5877
|
rowDrop = output();
|
|
5433
5878
|
/**
|
|
5434
5879
|
* Emitted on BOTH source and target grids after a successful cross-grid
|
|
5435
5880
|
* row transfer.
|
|
5881
|
+
*
|
|
5882
|
+
* @deprecated Use `GridRowDragDropDirective` from
|
|
5883
|
+
* `@toolbox-web/grid-angular/features/row-drag-drop`. Will be removed in v2.0.0.
|
|
5436
5884
|
*/
|
|
5437
5885
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5438
5886
|
rowTransfer = output();
|
|
@@ -5443,8 +5891,35 @@ class Grid {
|
|
|
5443
5891
|
* ```html
|
|
5444
5892
|
* <tbw-grid (groupToggle)="onGroupToggle($event)">...</tbw-grid>
|
|
5445
5893
|
* ```
|
|
5894
|
+
*
|
|
5895
|
+
* @deprecated Use `GridGroupingRowsDirective` from
|
|
5896
|
+
* `@toolbox-web/grid-angular/features/grouping-rows`. Will be removed in v2.0.0.
|
|
5446
5897
|
*/
|
|
5447
5898
|
groupToggle = output();
|
|
5899
|
+
/**
|
|
5900
|
+
* Emitted when a group is expanded.
|
|
5901
|
+
*
|
|
5902
|
+
* @example
|
|
5903
|
+
* ```html
|
|
5904
|
+
* <tbw-grid (groupExpand)="onGroupExpand($event)">...</tbw-grid>
|
|
5905
|
+
* ```
|
|
5906
|
+
*
|
|
5907
|
+
* @deprecated Use `GridGroupingRowsDirective` from
|
|
5908
|
+
* `@toolbox-web/grid-angular/features/grouping-rows`. Will be removed in v2.0.0.
|
|
5909
|
+
*/
|
|
5910
|
+
groupExpand = output();
|
|
5911
|
+
/**
|
|
5912
|
+
* Emitted when a group is collapsed.
|
|
5913
|
+
*
|
|
5914
|
+
* @example
|
|
5915
|
+
* ```html
|
|
5916
|
+
* <tbw-grid (groupCollapse)="onGroupCollapse($event)">...</tbw-grid>
|
|
5917
|
+
* ```
|
|
5918
|
+
*
|
|
5919
|
+
* @deprecated Use `GridGroupingRowsDirective` from
|
|
5920
|
+
* `@toolbox-web/grid-angular/features/grouping-rows`. Will be removed in v2.0.0.
|
|
5921
|
+
*/
|
|
5922
|
+
groupCollapse = output();
|
|
5448
5923
|
/**
|
|
5449
5924
|
* Emitted when a tree node is expanded.
|
|
5450
5925
|
*
|
|
@@ -5452,6 +5927,9 @@ class Grid {
|
|
|
5452
5927
|
* ```html
|
|
5453
5928
|
* <tbw-grid (treeExpand)="onTreeExpand($event)">...</tbw-grid>
|
|
5454
5929
|
* ```
|
|
5930
|
+
*
|
|
5931
|
+
* @deprecated Use `GridTreeDirective` from
|
|
5932
|
+
* `@toolbox-web/grid-angular/features/tree`. Will be removed in v2.0.0.
|
|
5455
5933
|
*/
|
|
5456
5934
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5457
5935
|
treeExpand = output();
|
|
@@ -5462,6 +5940,9 @@ class Grid {
|
|
|
5462
5940
|
* ```html
|
|
5463
5941
|
* <tbw-grid (detailExpand)="onDetailExpand($event)">...</tbw-grid>
|
|
5464
5942
|
* ```
|
|
5943
|
+
*
|
|
5944
|
+
* @deprecated Use `GridMasterDetailDirective` from
|
|
5945
|
+
* `@toolbox-web/grid-angular/features/master-detail`. Will be removed in v2.0.0.
|
|
5465
5946
|
*/
|
|
5466
5947
|
detailExpand = output();
|
|
5467
5948
|
/**
|
|
@@ -5471,8 +5952,23 @@ class Grid {
|
|
|
5471
5952
|
* ```html
|
|
5472
5953
|
* <tbw-grid (responsiveChange)="onResponsiveChange($event)">...</tbw-grid>
|
|
5473
5954
|
* ```
|
|
5955
|
+
*
|
|
5956
|
+
* @deprecated Use `GridResponsiveDirective` from
|
|
5957
|
+
* `@toolbox-web/grid-angular/features/responsive`. Will be removed in v2.0.0.
|
|
5474
5958
|
*/
|
|
5475
5959
|
responsiveChange = output();
|
|
5960
|
+
/**
|
|
5961
|
+
* Emitted when the context menu opens.
|
|
5962
|
+
*
|
|
5963
|
+
* @example
|
|
5964
|
+
* ```html
|
|
5965
|
+
* <tbw-grid (contextMenuOpen)="onContextMenuOpen($event)">...</tbw-grid>
|
|
5966
|
+
* ```
|
|
5967
|
+
*
|
|
5968
|
+
* @deprecated Use `GridContextMenuDirective` from
|
|
5969
|
+
* `@toolbox-web/grid-angular/features/context-menu`. Will be removed in v2.0.0.
|
|
5970
|
+
*/
|
|
5971
|
+
contextMenuOpen = output();
|
|
5476
5972
|
/**
|
|
5477
5973
|
* Emitted when cells are copied to clipboard.
|
|
5478
5974
|
*
|
|
@@ -5480,6 +5976,9 @@ class Grid {
|
|
|
5480
5976
|
* ```html
|
|
5481
5977
|
* <tbw-grid (copy)="onCopy($event)">...</tbw-grid>
|
|
5482
5978
|
* ```
|
|
5979
|
+
*
|
|
5980
|
+
* @deprecated Use `GridClipboardDirective` from
|
|
5981
|
+
* `@toolbox-web/grid-angular/features/clipboard`. Will be removed in v2.0.0.
|
|
5483
5982
|
*/
|
|
5484
5983
|
copy = output();
|
|
5485
5984
|
/**
|
|
@@ -5489,17 +5988,35 @@ class Grid {
|
|
|
5489
5988
|
* ```html
|
|
5490
5989
|
* <tbw-grid (paste)="onPaste($event)">...</tbw-grid>
|
|
5491
5990
|
* ```
|
|
5991
|
+
*
|
|
5992
|
+
* @deprecated Use `GridClipboardDirective` from
|
|
5993
|
+
* `@toolbox-web/grid-angular/features/clipboard`. Will be removed in v2.0.0.
|
|
5492
5994
|
*/
|
|
5493
5995
|
paste = output();
|
|
5494
5996
|
/**
|
|
5495
|
-
* Emitted when undo
|
|
5997
|
+
* Emitted when an undo action is performed.
|
|
5998
|
+
*
|
|
5999
|
+
* @example
|
|
6000
|
+
* ```html
|
|
6001
|
+
* <tbw-grid (undo)="onUndo($event)">...</tbw-grid>
|
|
6002
|
+
* ```
|
|
6003
|
+
*
|
|
6004
|
+
* @deprecated Use `GridUndoRedoDirective` from
|
|
6005
|
+
* `@toolbox-web/grid-angular/features/undo-redo`. Will be removed in v2.0.0.
|
|
6006
|
+
*/
|
|
6007
|
+
undo = output();
|
|
6008
|
+
/**
|
|
6009
|
+
* Emitted when a redo action is performed.
|
|
5496
6010
|
*
|
|
5497
6011
|
* @example
|
|
5498
6012
|
* ```html
|
|
5499
|
-
* <tbw-grid (
|
|
6013
|
+
* <tbw-grid (redo)="onRedo($event)">...</tbw-grid>
|
|
5500
6014
|
* ```
|
|
6015
|
+
*
|
|
6016
|
+
* @deprecated Use `GridUndoRedoDirective` from
|
|
6017
|
+
* `@toolbox-web/grid-angular/features/undo-redo`. Will be removed in v2.0.0.
|
|
5501
6018
|
*/
|
|
5502
|
-
|
|
6019
|
+
redo = output();
|
|
5503
6020
|
/**
|
|
5504
6021
|
* Emitted when export completes.
|
|
5505
6022
|
*
|
|
@@ -5507,6 +6024,9 @@ class Grid {
|
|
|
5507
6024
|
* ```html
|
|
5508
6025
|
* <tbw-grid (exportComplete)="onExportComplete($event)">...</tbw-grid>
|
|
5509
6026
|
* ```
|
|
6027
|
+
*
|
|
6028
|
+
* @deprecated Use `GridExportDirective` from
|
|
6029
|
+
* `@toolbox-web/grid-angular/features/export`. Will be removed in v2.0.0.
|
|
5510
6030
|
*/
|
|
5511
6031
|
exportComplete = output();
|
|
5512
6032
|
/**
|
|
@@ -5516,6 +6036,9 @@ class Grid {
|
|
|
5516
6036
|
* ```html
|
|
5517
6037
|
* <tbw-grid (printStart)="onPrintStart($event)">...</tbw-grid>
|
|
5518
6038
|
* ```
|
|
6039
|
+
*
|
|
6040
|
+
* @deprecated Use `GridPrintDirective` from
|
|
6041
|
+
* `@toolbox-web/grid-angular/features/print`. Will be removed in v2.0.0.
|
|
5519
6042
|
*/
|
|
5520
6043
|
printStart = output();
|
|
5521
6044
|
/**
|
|
@@ -5525,6 +6048,9 @@ class Grid {
|
|
|
5525
6048
|
* ```html
|
|
5526
6049
|
* <tbw-grid (printComplete)="onPrintComplete($event)">...</tbw-grid>
|
|
5527
6050
|
* ```
|
|
6051
|
+
*
|
|
6052
|
+
* @deprecated Use `GridPrintDirective` from
|
|
6053
|
+
* `@toolbox-web/grid-angular/features/print`. Will be removed in v2.0.0.
|
|
5528
6054
|
*/
|
|
5529
6055
|
printComplete = output();
|
|
5530
6056
|
/**
|
|
@@ -5543,18 +6069,31 @@ class Grid {
|
|
|
5543
6069
|
* ```
|
|
5544
6070
|
*/
|
|
5545
6071
|
tbwScroll = output();
|
|
5546
|
-
// Map of output names to event names for automatic wiring
|
|
6072
|
+
// Map of output names to event names for automatic wiring.
|
|
6073
|
+
//
|
|
6074
|
+
// The `satisfies` clause enforces compile-time sync against
|
|
6075
|
+
// `DataGridEventMap`: every value must be a real event name (typos and
|
|
6076
|
+
// stale entries pointing at non-existent events fail to compile).
|
|
6077
|
+
// Plugin event augmentations of `DataGridEventMap` flow through
|
|
6078
|
+
// automatically via the `/all` import.
|
|
5547
6079
|
eventOutputMap = {
|
|
5548
6080
|
cellClick: 'cell-click',
|
|
5549
6081
|
rowClick: 'row-click',
|
|
5550
6082
|
cellActivate: 'cell-activate',
|
|
5551
6083
|
cellChange: 'cell-change',
|
|
5552
6084
|
cellCommit: 'cell-commit',
|
|
6085
|
+
cellCancel: 'cell-cancel',
|
|
5553
6086
|
rowCommit: 'row-commit',
|
|
5554
6087
|
changedRowsReset: 'changed-rows-reset',
|
|
6088
|
+
editOpen: 'edit-open',
|
|
6089
|
+
beforeEditClose: 'before-edit-close',
|
|
6090
|
+
editClose: 'edit-close',
|
|
6091
|
+
dirtyChange: 'dirty-change',
|
|
6092
|
+
dataChange: 'data-change',
|
|
5555
6093
|
sortChange: 'sort-change',
|
|
5556
6094
|
filterChange: 'filter-change',
|
|
5557
6095
|
columnResize: 'column-resize',
|
|
6096
|
+
columnResizeReset: 'column-resize-reset',
|
|
5558
6097
|
columnMove: 'column-move',
|
|
5559
6098
|
columnVisibility: 'column-visibility',
|
|
5560
6099
|
columnStateChange: 'column-state-change',
|
|
@@ -5565,17 +6104,39 @@ class Grid {
|
|
|
5565
6104
|
rowDrop: 'row-drop',
|
|
5566
6105
|
rowTransfer: 'row-transfer',
|
|
5567
6106
|
groupToggle: 'group-toggle',
|
|
6107
|
+
groupExpand: 'group-expand',
|
|
6108
|
+
groupCollapse: 'group-collapse',
|
|
5568
6109
|
treeExpand: 'tree-expand',
|
|
5569
6110
|
detailExpand: 'detail-expand',
|
|
5570
6111
|
responsiveChange: 'responsive-change',
|
|
6112
|
+
contextMenuOpen: 'context-menu-open',
|
|
5571
6113
|
copy: 'copy',
|
|
5572
6114
|
paste: 'paste',
|
|
5573
|
-
|
|
6115
|
+
undo: 'undo',
|
|
6116
|
+
redo: 'redo',
|
|
5574
6117
|
exportComplete: 'export-complete',
|
|
5575
6118
|
printStart: 'print-start',
|
|
5576
6119
|
printComplete: 'print-complete',
|
|
5577
6120
|
tbwScroll: 'tbw-scroll',
|
|
5578
6121
|
};
|
|
6122
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
6123
|
+
// Forward-only event coverage guard.
|
|
6124
|
+
//
|
|
6125
|
+
// Mirrors the React adapter's `_AssertFeaturePropsCoverCore` pattern. If a
|
|
6126
|
+
// new event is added to core's `DataGridEventMap` (via plugin module
|
|
6127
|
+
// augmentation in `/all`) but no `eventOutputMap` entry covers it, this
|
|
6128
|
+
// type fails to evaluate to `true` and the build breaks. Adapter consumers
|
|
6129
|
+
// never see a silently-dropped event.
|
|
6130
|
+
//
|
|
6131
|
+
// Reverse direction (extra `eventOutputMap` entries pointing at non-existent
|
|
6132
|
+
// events) is already enforced by the `satisfies` clause above.
|
|
6133
|
+
//
|
|
6134
|
+
// To consciously omit an event from the Angular surface, add it to the
|
|
6135
|
+
// `IntentionallyOmittedEvents` union below with a comment explaining why.
|
|
6136
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
6137
|
+
/** Events deliberately not exposed as Angular outputs. Keep empty unless documented. */
|
|
6138
|
+
_intentionallyOmittedEvents;
|
|
6139
|
+
_assertEventOutputMapCoversCore;
|
|
5579
6140
|
// Store event listeners for cleanup
|
|
5580
6141
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5581
6142
|
eventListeners = new Map();
|
|
@@ -5594,10 +6155,18 @@ class Grid {
|
|
|
5594
6155
|
}
|
|
5595
6156
|
/**
|
|
5596
6157
|
* Sets up event listeners for all outputs using the eventOutputMap.
|
|
6158
|
+
*
|
|
6159
|
+
* Hybrid v1.x / v2 ownership: events claimed by an attribute-selector
|
|
6160
|
+
* feature directive (via `claimEvent` in `feature-claims.ts`) are skipped
|
|
6161
|
+
* here so the directive's own `output()` is the sole emitter. Without
|
|
6162
|
+
* this skip both this directive's deprecated output and the directive's
|
|
6163
|
+
* new output would fire for the same DOM event.
|
|
5597
6164
|
*/
|
|
5598
6165
|
setupEventListeners(grid) {
|
|
5599
6166
|
// Wire up all event listeners
|
|
5600
6167
|
for (const [outputName, eventName] of Object.entries(this.eventOutputMap)) {
|
|
6168
|
+
if (isEventClaimed(grid, eventName))
|
|
6169
|
+
continue;
|
|
5601
6170
|
const listener = (e) => {
|
|
5602
6171
|
const detail = e.detail;
|
|
5603
6172
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -5610,57 +6179,62 @@ class Grid {
|
|
|
5610
6179
|
/**
|
|
5611
6180
|
* Creates plugins from feature inputs.
|
|
5612
6181
|
* Uses the feature registry to allow tree-shaking - only imported features are bundled.
|
|
6182
|
+
* Per-feature config bridging (e.g. converting Angular component classes inside
|
|
6183
|
+
* `groupingColumns` / `groupingRows` / `pinnedRows` configs to renderer functions)
|
|
6184
|
+
* runs via `getFeatureConfigPreprocessor`, populated by feature secondary entries.
|
|
6185
|
+
*
|
|
6186
|
+
* Hybrid v1.x / v2 ownership: when an attribute-selector feature directive
|
|
6187
|
+
* (e.g. `GridFilteringDirective`) is present on the same `<tbw-grid>`
|
|
6188
|
+
* element it claims its feature in `feature-claims.ts`. We then read the
|
|
6189
|
+
* claim's config getter — which transitively reads the directive's input
|
|
6190
|
+
* signal, establishing reactive dependency tracking — instead of the
|
|
6191
|
+
* deprecated input on this directive. This keeps the existing `[filtering]`
|
|
6192
|
+
* binding working when used directly on `<tbw-grid>` (no directive, no
|
|
6193
|
+
* claim) while letting the directive own the binding when imported.
|
|
6194
|
+
*
|
|
5613
6195
|
* Returns the array of created plugins (doesn't modify grid).
|
|
5614
6196
|
*/
|
|
5615
6197
|
createFeaturePlugins() {
|
|
5616
6198
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5617
6199
|
const plugins = [];
|
|
6200
|
+
const adapter = this.adapter;
|
|
6201
|
+
const grid = this.elementRef.nativeElement;
|
|
5618
6202
|
// Helper to add plugin if feature is registered
|
|
5619
|
-
const addPlugin = (name,
|
|
6203
|
+
const addPlugin = (name, ownInput) => {
|
|
6204
|
+
// Directive-owned config wins. Reading the claim's getter inside this
|
|
6205
|
+
// effect registers the directive's input signal as a dependency, so
|
|
6206
|
+
// changes to e.g. `[filtering]` on the directive re-trigger this effect.
|
|
6207
|
+
const claim = getFeatureClaim(grid, name);
|
|
6208
|
+
const config = claim ? claim() : ownInput;
|
|
5620
6209
|
if (config === undefined || config === null || config === false)
|
|
5621
6210
|
return;
|
|
5622
|
-
|
|
6211
|
+
// Apply per-feature config preprocessor (registered by feature secondary entries)
|
|
6212
|
+
// to bridge Angular component classes embedded in the config before instantiation.
|
|
6213
|
+
let finalConfig = config;
|
|
6214
|
+
if (adapter && config !== true && typeof config === 'object') {
|
|
6215
|
+
const preprocess = getFeatureConfigPreprocessor(name);
|
|
6216
|
+
if (preprocess)
|
|
6217
|
+
finalConfig = preprocess(config, adapter);
|
|
6218
|
+
}
|
|
6219
|
+
const plugin = createPluginFromFeature(name, finalConfig);
|
|
5623
6220
|
if (plugin)
|
|
5624
6221
|
plugins.push(plugin);
|
|
5625
6222
|
};
|
|
5626
|
-
// Add plugins for each feature input
|
|
5627
6223
|
addPlugin('selection', this.selection());
|
|
5628
6224
|
addPlugin('editing', this.editing());
|
|
5629
6225
|
addPlugin('clipboard', this.clipboard());
|
|
5630
6226
|
addPlugin('contextMenu', this.contextMenu());
|
|
5631
|
-
// multiSort is the primary input
|
|
5632
6227
|
addPlugin('multiSort', this.multiSort());
|
|
5633
6228
|
addPlugin('filtering', this.filtering());
|
|
5634
6229
|
addPlugin('reorderColumns', this.reorderColumns());
|
|
5635
6230
|
addPlugin('visibility', this.visibility());
|
|
5636
6231
|
addPlugin('pinnedColumns', this.pinnedColumns());
|
|
5637
|
-
|
|
5638
|
-
const gcConfig = this.groupingColumns();
|
|
5639
|
-
if (gcConfig && typeof gcConfig === 'object' && this.adapter) {
|
|
5640
|
-
addPlugin('groupingColumns', this.adapter.processGroupingColumnsConfig(gcConfig));
|
|
5641
|
-
}
|
|
5642
|
-
else {
|
|
5643
|
-
addPlugin('groupingColumns', gcConfig);
|
|
5644
|
-
}
|
|
6232
|
+
addPlugin('groupingColumns', this.groupingColumns());
|
|
5645
6233
|
addPlugin('columnVirtualization', this.columnVirtualization());
|
|
5646
6234
|
addPlugin('reorderRows', this.reorderRows());
|
|
5647
6235
|
addPlugin('rowDragDrop', this.rowDragDrop());
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
if (grConfig && typeof grConfig === 'object' && this.adapter) {
|
|
5651
|
-
addPlugin('groupingRows', this.adapter.processGroupingRowsConfig(grConfig));
|
|
5652
|
-
}
|
|
5653
|
-
else {
|
|
5654
|
-
addPlugin('groupingRows', grConfig);
|
|
5655
|
-
}
|
|
5656
|
-
// Pre-process pinnedRows config to bridge Angular component classes in customPanels
|
|
5657
|
-
const prConfig = this.pinnedRows();
|
|
5658
|
-
if (prConfig && typeof prConfig === 'object' && this.adapter) {
|
|
5659
|
-
addPlugin('pinnedRows', this.adapter.processPinnedRowsConfig(prConfig));
|
|
5660
|
-
}
|
|
5661
|
-
else {
|
|
5662
|
-
addPlugin('pinnedRows', prConfig);
|
|
5663
|
-
}
|
|
6236
|
+
addPlugin('groupingRows', this.groupingRows());
|
|
6237
|
+
addPlugin('pinnedRows', this.pinnedRows());
|
|
5664
6238
|
addPlugin('tree', this.tree());
|
|
5665
6239
|
addPlugin('masterDetail', this.masterDetail());
|
|
5666
6240
|
addPlugin('responsive', this.responsive());
|
|
@@ -5680,10 +6254,13 @@ class Grid {
|
|
|
5680
6254
|
// Use setTimeout to ensure Angular effects have run (template registration)
|
|
5681
6255
|
setTimeout(() => {
|
|
5682
6256
|
grid.refreshColumns();
|
|
5683
|
-
//
|
|
5684
|
-
|
|
5685
|
-
//
|
|
5686
|
-
|
|
6257
|
+
// Run feature-registered template bridges. Each bridge wires a specific
|
|
6258
|
+
// light-DOM slot element (<tbw-grid-detail>, <tbw-grid-responsive-card>, ...)
|
|
6259
|
+
// to its plugin. Bridges are registered by feature secondary entries
|
|
6260
|
+
// (e.g. `import '@toolbox-web/grid-angular/features/master-detail';`).
|
|
6261
|
+
if (this.adapter) {
|
|
6262
|
+
runTemplateBridges({ grid, adapter: this.adapter });
|
|
6263
|
+
}
|
|
5687
6264
|
// Refresh shell header to pick up tool panel templates
|
|
5688
6265
|
// This allows Angular templates to be used in tool panels
|
|
5689
6266
|
if (typeof grid.refreshShellHeader === 'function') {
|
|
@@ -5707,85 +6284,6 @@ class Grid {
|
|
|
5707
6284
|
grid.registerStyles?.('angular-custom-styles', styles);
|
|
5708
6285
|
});
|
|
5709
6286
|
}
|
|
5710
|
-
/**
|
|
5711
|
-
* Configures the MasterDetailPlugin after Angular templates are registered.
|
|
5712
|
-
* - If plugin exists: refresh its detail renderer
|
|
5713
|
-
* - If plugin doesn't exist but <tbw-grid-detail> is present: dynamically import and add the plugin
|
|
5714
|
-
*/
|
|
5715
|
-
async configureMasterDetail(grid) {
|
|
5716
|
-
if (!this.adapter)
|
|
5717
|
-
return;
|
|
5718
|
-
// Check for existing plugin by name to avoid importing the class
|
|
5719
|
-
const existingPlugin = grid.gridConfig?.plugins?.find((p) => p.name === 'masterDetail');
|
|
5720
|
-
if (existingPlugin && typeof existingPlugin.refreshDetailRenderer === 'function') {
|
|
5721
|
-
// Plugin exists - just refresh the renderer to pick up Angular templates
|
|
5722
|
-
existingPlugin.refreshDetailRenderer();
|
|
5723
|
-
return;
|
|
5724
|
-
}
|
|
5725
|
-
// Check if <tbw-grid-detail> is present in light DOM
|
|
5726
|
-
const detailElement = grid.querySelector('tbw-grid-detail');
|
|
5727
|
-
if (!detailElement)
|
|
5728
|
-
return;
|
|
5729
|
-
// Create detail renderer from Angular template
|
|
5730
|
-
const detailRenderer = this.adapter.createDetailRenderer(grid);
|
|
5731
|
-
if (!detailRenderer)
|
|
5732
|
-
return;
|
|
5733
|
-
// Parse configuration from attributes
|
|
5734
|
-
const animationAttr = detailElement.getAttribute('animation');
|
|
5735
|
-
let animation = 'slide';
|
|
5736
|
-
if (animationAttr === 'false') {
|
|
5737
|
-
animation = false;
|
|
5738
|
-
}
|
|
5739
|
-
else if (animationAttr === 'fade') {
|
|
5740
|
-
animation = 'fade';
|
|
5741
|
-
}
|
|
5742
|
-
const showExpandColumn = detailElement.getAttribute('showExpandColumn') !== 'false';
|
|
5743
|
-
// Dynamically import the plugin to avoid bundling it when not used
|
|
5744
|
-
const { MasterDetailPlugin } = await import('@toolbox-web/grid/plugins/master-detail');
|
|
5745
|
-
// Create and add the plugin
|
|
5746
|
-
const plugin = new MasterDetailPlugin({
|
|
5747
|
-
detailRenderer: detailRenderer,
|
|
5748
|
-
showExpandColumn,
|
|
5749
|
-
animation,
|
|
5750
|
-
});
|
|
5751
|
-
const currentConfig = grid.gridConfig || {};
|
|
5752
|
-
const existingPlugins = currentConfig.plugins || [];
|
|
5753
|
-
grid.gridConfig = {
|
|
5754
|
-
...currentConfig,
|
|
5755
|
-
plugins: [...existingPlugins, plugin],
|
|
5756
|
-
};
|
|
5757
|
-
}
|
|
5758
|
-
/**
|
|
5759
|
-
* Configures the ResponsivePlugin with Angular template-based card renderer.
|
|
5760
|
-
* - If plugin exists: updates its cardRenderer configuration
|
|
5761
|
-
* - If plugin doesn't exist but <tbw-grid-responsive-card> is present: logs a warning
|
|
5762
|
-
*/
|
|
5763
|
-
configureResponsiveCard(grid) {
|
|
5764
|
-
if (!this.adapter)
|
|
5765
|
-
return;
|
|
5766
|
-
// Check if <tbw-grid-responsive-card> is present in light DOM
|
|
5767
|
-
const cardElement = grid.querySelector('tbw-grid-responsive-card');
|
|
5768
|
-
if (!cardElement)
|
|
5769
|
-
return;
|
|
5770
|
-
// Create card renderer from Angular template
|
|
5771
|
-
const cardRenderer = this.adapter.createResponsiveCardRenderer(grid);
|
|
5772
|
-
if (!cardRenderer)
|
|
5773
|
-
return;
|
|
5774
|
-
// Find existing plugin by name to avoid importing the class
|
|
5775
|
-
const existingPlugin = grid.gridConfig?.plugins?.find((p) => p.name === 'responsive');
|
|
5776
|
-
if (existingPlugin && typeof existingPlugin.setCardRenderer === 'function') {
|
|
5777
|
-
// Plugin exists - update its cardRenderer
|
|
5778
|
-
existingPlugin.setCardRenderer(cardRenderer);
|
|
5779
|
-
return;
|
|
5780
|
-
}
|
|
5781
|
-
// Plugin doesn't exist - log a warning
|
|
5782
|
-
console.warn('[tbw-grid-angular] <tbw-grid-responsive-card> found but ResponsivePlugin is not configured.\n' +
|
|
5783
|
-
'Add ResponsivePlugin to your gridConfig.plugins array:\n\n' +
|
|
5784
|
-
' import { ResponsivePlugin } from "@toolbox-web/grid/plugins/responsive";\n' +
|
|
5785
|
-
' gridConfig = {\n' +
|
|
5786
|
-
' plugins: [new ResponsivePlugin({ breakpoint: 600 })]\n' +
|
|
5787
|
-
' };');
|
|
5788
|
-
}
|
|
5789
6287
|
ngOnDestroy() {
|
|
5790
6288
|
const grid = this.elementRef.nativeElement;
|
|
5791
6289
|
// Cleanup all event listeners
|
|
@@ -5806,12 +6304,61 @@ class Grid {
|
|
|
5806
6304
|
}
|
|
5807
6305
|
}
|
|
5808
6306
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Grid, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
5809
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: Grid, isStandalone: true, selector: "tbw-grid", inputs: { customStyles: { classPropertyName: "customStyles", publicName: "customStyles", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, fitMode: { classPropertyName: "fitMode", publicName: "fitMode", isSignal: true, isRequired: false, transformFunction: null }, gridConfig: { classPropertyName: "gridConfig", publicName: "gridConfig", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null }, clipboard: { classPropertyName: "clipboard", publicName: "clipboard", isSignal: true, isRequired: false, transformFunction: null }, contextMenu: { classPropertyName: "contextMenu", publicName: "contextMenu", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, filtering: { classPropertyName: "filtering", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, reorderColumns: { classPropertyName: "reorderColumns", publicName: "reorderColumns", isSignal: true, isRequired: false, transformFunction: null }, visibility: { classPropertyName: "visibility", publicName: "visibility", isSignal: true, isRequired: false, transformFunction: null }, pinnedColumns: { classPropertyName: "pinnedColumns", publicName: "pinnedColumns", isSignal: true, isRequired: false, transformFunction: null }, groupingColumns: { classPropertyName: "groupingColumns", publicName: "groupingColumns", isSignal: true, isRequired: false, transformFunction: null }, columnVirtualization: { classPropertyName: "columnVirtualization", publicName: "columnVirtualization", isSignal: true, isRequired: false, transformFunction: null }, reorderRows: { classPropertyName: "reorderRows", publicName: "reorderRows", isSignal: true, isRequired: false, transformFunction: null }, rowDragDrop: { classPropertyName: "rowDragDrop", publicName: "rowDragDrop", isSignal: true, isRequired: false, transformFunction: null }, groupingRows: { classPropertyName: "groupingRows", publicName: "groupingRows", isSignal: true, isRequired: false, transformFunction: null }, pinnedRows: { classPropertyName: "pinnedRows", publicName: "pinnedRows", isSignal: true, isRequired: false, transformFunction: null }, tree: { classPropertyName: "tree", publicName: "tree", isSignal: true, isRequired: false, transformFunction: null }, masterDetail: { classPropertyName: "masterDetail", publicName: "masterDetail", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, undoRedo: { classPropertyName: "undoRedo", publicName: "undoRedo", isSignal: true, isRequired: false, transformFunction: null }, exportFeature: { classPropertyName: "exportFeature", publicName: "export", isSignal: true, isRequired: false, transformFunction: null }, print: { classPropertyName: "print", publicName: "print", isSignal: true, isRequired: false, transformFunction: null }, pivot: { classPropertyName: "pivot", publicName: "pivot", isSignal: true, isRequired: false, transformFunction: null }, serverSide: { classPropertyName: "serverSide", publicName: "serverSide", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellClick: "cellClick", rowClick: "rowClick", cellActivate: "cellActivate", cellChange: "cellChange", cellCommit: "cellCommit", rowCommit: "rowCommit", changedRowsReset: "changedRowsReset", sortChange: "sortChange", filterChange: "filterChange", columnResize: "columnResize", columnMove: "columnMove", columnVisibility: "columnVisibility", columnStateChange: "columnStateChange", selectionChange: "selectionChange", rowMove: "rowMove", rowDragStart: "rowDragStart", rowDragEnd: "rowDragEnd", rowDrop: "rowDrop", rowTransfer: "rowTransfer", groupToggle: "groupToggle", treeExpand: "treeExpand", detailExpand: "detailExpand", responsiveChange: "responsiveChange", copy: "copy", paste: "paste",
|
|
6307
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: Grid, isStandalone: true, selector: "tbw-grid", inputs: { customStyles: { classPropertyName: "customStyles", publicName: "customStyles", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, columnDefaults: { classPropertyName: "columnDefaults", publicName: "columnDefaults", isSignal: true, isRequired: false, transformFunction: null }, fitMode: { classPropertyName: "fitMode", publicName: "fitMode", isSignal: true, isRequired: false, transformFunction: null }, gridConfig: { classPropertyName: "gridConfig", publicName: "gridConfig", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null }, clipboard: { classPropertyName: "clipboard", publicName: "clipboard", isSignal: true, isRequired: false, transformFunction: null }, contextMenu: { classPropertyName: "contextMenu", publicName: "contextMenu", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, filtering: { classPropertyName: "filtering", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, reorderColumns: { classPropertyName: "reorderColumns", publicName: "reorderColumns", isSignal: true, isRequired: false, transformFunction: null }, visibility: { classPropertyName: "visibility", publicName: "visibility", isSignal: true, isRequired: false, transformFunction: null }, pinnedColumns: { classPropertyName: "pinnedColumns", publicName: "pinnedColumns", isSignal: true, isRequired: false, transformFunction: null }, groupingColumns: { classPropertyName: "groupingColumns", publicName: "groupingColumns", isSignal: true, isRequired: false, transformFunction: null }, columnVirtualization: { classPropertyName: "columnVirtualization", publicName: "columnVirtualization", isSignal: true, isRequired: false, transformFunction: null }, reorderRows: { classPropertyName: "reorderRows", publicName: "reorderRows", isSignal: true, isRequired: false, transformFunction: null }, rowDragDrop: { classPropertyName: "rowDragDrop", publicName: "rowDragDrop", isSignal: true, isRequired: false, transformFunction: null }, groupingRows: { classPropertyName: "groupingRows", publicName: "groupingRows", isSignal: true, isRequired: false, transformFunction: null }, pinnedRows: { classPropertyName: "pinnedRows", publicName: "pinnedRows", isSignal: true, isRequired: false, transformFunction: null }, tree: { classPropertyName: "tree", publicName: "tree", isSignal: true, isRequired: false, transformFunction: null }, masterDetail: { classPropertyName: "masterDetail", publicName: "masterDetail", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, undoRedo: { classPropertyName: "undoRedo", publicName: "undoRedo", isSignal: true, isRequired: false, transformFunction: null }, exportFeature: { classPropertyName: "exportFeature", publicName: "export", isSignal: true, isRequired: false, transformFunction: null }, print: { classPropertyName: "print", publicName: "print", isSignal: true, isRequired: false, transformFunction: null }, pivot: { classPropertyName: "pivot", publicName: "pivot", isSignal: true, isRequired: false, transformFunction: null }, serverSide: { classPropertyName: "serverSide", publicName: "serverSide", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellClick: "cellClick", rowClick: "rowClick", cellActivate: "cellActivate", cellChange: "cellChange", cellCommit: "cellCommit", cellCancel: "cellCancel", editOpen: "editOpen", beforeEditClose: "beforeEditClose", editClose: "editClose", dirtyChange: "dirtyChange", dataChange: "dataChange", rowCommit: "rowCommit", changedRowsReset: "changedRowsReset", sortChange: "sortChange", filterChange: "filterChange", columnResize: "columnResize", columnResizeReset: "columnResizeReset", columnMove: "columnMove", columnVisibility: "columnVisibility", columnStateChange: "columnStateChange", selectionChange: "selectionChange", rowMove: "rowMove", rowDragStart: "rowDragStart", rowDragEnd: "rowDragEnd", rowDrop: "rowDrop", rowTransfer: "rowTransfer", groupToggle: "groupToggle", groupExpand: "groupExpand", groupCollapse: "groupCollapse", treeExpand: "treeExpand", detailExpand: "detailExpand", responsiveChange: "responsiveChange", contextMenuOpen: "contextMenuOpen", copy: "copy", paste: "paste", undo: "undo", redo: "redo", exportComplete: "exportComplete", printStart: "printStart", printComplete: "printComplete", tbwScroll: "tbwScroll" }, ngImport: i0 });
|
|
5810
6308
|
}
|
|
5811
6309
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: Grid, decorators: [{
|
|
5812
6310
|
type: Directive,
|
|
5813
6311
|
args: [{ selector: 'tbw-grid' }]
|
|
5814
|
-
}], ctorParameters: () => [], propDecorators: { customStyles: [{ type: i0.Input, args: [{ isSignal: true, alias: "customStyles", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], fitMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitMode", required: false }] }], gridConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridConfig", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], clipboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "clipboard", required: false }] }], contextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextMenu", required: false }] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], filtering: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], reorderColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderColumns", required: false }] }], visibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibility", required: false }] }], pinnedColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedColumns", required: false }] }], groupingColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupingColumns", required: false }] }], columnVirtualization: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnVirtualization", required: false }] }], reorderRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderRows", required: false }] }], rowDragDrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDragDrop", required: false }] }], groupingRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupingRows", required: false }] }], pinnedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedRows", required: false }] }], tree: [{ type: i0.Input, args: [{ isSignal: true, alias: "tree", required: false }] }], masterDetail: [{ type: i0.Input, args: [{ isSignal: true, alias: "masterDetail", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], undoRedo: [{ type: i0.Input, args: [{ isSignal: true, alias: "undoRedo", required: false }] }], exportFeature: [{ type: i0.Input, args: [{ isSignal: true, alias: "export", required: false }] }], print: [{ type: i0.Input, args: [{ isSignal: true, alias: "print", required: false }] }], pivot: [{ type: i0.Input, args: [{ isSignal: true, alias: "pivot", required: false }] }], serverSide: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSide", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellActivate: [{ type: i0.Output, args: ["cellActivate"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], rowCommit: [{ type: i0.Output, args: ["rowCommit"] }], changedRowsReset: [{ type: i0.Output, args: ["changedRowsReset"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnMove: [{ type: i0.Output, args: ["columnMove"] }], columnVisibility: [{ type: i0.Output, args: ["columnVisibility"] }], columnStateChange: [{ type: i0.Output, args: ["columnStateChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowMove: [{ type: i0.Output, args: ["rowMove"] }], rowDragStart: [{ type: i0.Output, args: ["rowDragStart"] }], rowDragEnd: [{ type: i0.Output, args: ["rowDragEnd"] }], rowDrop: [{ type: i0.Output, args: ["rowDrop"] }], rowTransfer: [{ type: i0.Output, args: ["rowTransfer"] }], groupToggle: [{ type: i0.Output, args: ["groupToggle"] }], treeExpand: [{ type: i0.Output, args: ["treeExpand"] }], detailExpand: [{ type: i0.Output, args: ["detailExpand"] }], responsiveChange: [{ type: i0.Output, args: ["responsiveChange"] }], copy: [{ type: i0.Output, args: ["copy"] }], paste: [{ type: i0.Output, args: ["paste"] }],
|
|
6312
|
+
}], ctorParameters: () => [], propDecorators: { customStyles: [{ type: i0.Input, args: [{ isSignal: true, alias: "customStyles", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], columnDefaults: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnDefaults", required: false }] }], fitMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitMode", required: false }] }], gridConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridConfig", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], clipboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "clipboard", required: false }] }], contextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextMenu", required: false }] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], filtering: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], reorderColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderColumns", required: false }] }], visibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibility", required: false }] }], pinnedColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedColumns", required: false }] }], groupingColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupingColumns", required: false }] }], columnVirtualization: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnVirtualization", required: false }] }], reorderRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderRows", required: false }] }], rowDragDrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDragDrop", required: false }] }], groupingRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupingRows", required: false }] }], pinnedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedRows", required: false }] }], tree: [{ type: i0.Input, args: [{ isSignal: true, alias: "tree", required: false }] }], masterDetail: [{ type: i0.Input, args: [{ isSignal: true, alias: "masterDetail", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], undoRedo: [{ type: i0.Input, args: [{ isSignal: true, alias: "undoRedo", required: false }] }], exportFeature: [{ type: i0.Input, args: [{ isSignal: true, alias: "export", required: false }] }], print: [{ type: i0.Input, args: [{ isSignal: true, alias: "print", required: false }] }], pivot: [{ type: i0.Input, args: [{ isSignal: true, alias: "pivot", required: false }] }], serverSide: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSide", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cellActivate: [{ type: i0.Output, args: ["cellActivate"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], cellCancel: [{ type: i0.Output, args: ["cellCancel"] }], editOpen: [{ type: i0.Output, args: ["editOpen"] }], beforeEditClose: [{ type: i0.Output, args: ["beforeEditClose"] }], editClose: [{ type: i0.Output, args: ["editClose"] }], dirtyChange: [{ type: i0.Output, args: ["dirtyChange"] }], dataChange: [{ type: i0.Output, args: ["dataChange"] }], rowCommit: [{ type: i0.Output, args: ["rowCommit"] }], changedRowsReset: [{ type: i0.Output, args: ["changedRowsReset"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnResizeReset: [{ type: i0.Output, args: ["columnResizeReset"] }], columnMove: [{ type: i0.Output, args: ["columnMove"] }], columnVisibility: [{ type: i0.Output, args: ["columnVisibility"] }], columnStateChange: [{ type: i0.Output, args: ["columnStateChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowMove: [{ type: i0.Output, args: ["rowMove"] }], rowDragStart: [{ type: i0.Output, args: ["rowDragStart"] }], rowDragEnd: [{ type: i0.Output, args: ["rowDragEnd"] }], rowDrop: [{ type: i0.Output, args: ["rowDrop"] }], rowTransfer: [{ type: i0.Output, args: ["rowTransfer"] }], groupToggle: [{ type: i0.Output, args: ["groupToggle"] }], groupExpand: [{ type: i0.Output, args: ["groupExpand"] }], groupCollapse: [{ type: i0.Output, args: ["groupCollapse"] }], treeExpand: [{ type: i0.Output, args: ["treeExpand"] }], detailExpand: [{ type: i0.Output, args: ["detailExpand"] }], responsiveChange: [{ type: i0.Output, args: ["responsiveChange"] }], contextMenuOpen: [{ type: i0.Output, args: ["contextMenuOpen"] }], copy: [{ type: i0.Output, args: ["copy"] }], paste: [{ type: i0.Output, args: ["paste"] }], undo: [{ type: i0.Output, args: ["undo"] }], redo: [{ type: i0.Output, args: ["redo"] }], exportComplete: [{ type: i0.Output, args: ["exportComplete"] }], printStart: [{ type: i0.Output, args: ["printStart"] }], printComplete: [{ type: i0.Output, args: ["printComplete"] }], tbwScroll: [{ type: i0.Output, args: ["tbwScroll"] }] } });
|
|
6313
|
+
|
|
6314
|
+
/**
|
|
6315
|
+
* Combined provider helper for grid type defaults and icons.
|
|
6316
|
+
*
|
|
6317
|
+
* Convenience function that combines `provideGridTypeDefaults` and
|
|
6318
|
+
* `provideGridIcons` into a single call for application bootstrap.
|
|
6319
|
+
*
|
|
6320
|
+
* @example
|
|
6321
|
+
* ```typescript
|
|
6322
|
+
* // app.config.ts
|
|
6323
|
+
* import { ApplicationConfig } from '@angular/core';
|
|
6324
|
+
* import { provideGrid } from '@toolbox-web/grid-angular';
|
|
6325
|
+
*
|
|
6326
|
+
* export const appConfig: ApplicationConfig = {
|
|
6327
|
+
* providers: [
|
|
6328
|
+
* provideGrid({
|
|
6329
|
+
* typeDefaults: {
|
|
6330
|
+
* country: { renderer: CountryCellComponent },
|
|
6331
|
+
* },
|
|
6332
|
+
* icons: {
|
|
6333
|
+
* sortAsc: '↑',
|
|
6334
|
+
* sortDesc: '↓',
|
|
6335
|
+
* },
|
|
6336
|
+
* }),
|
|
6337
|
+
* ],
|
|
6338
|
+
* };
|
|
6339
|
+
* ```
|
|
6340
|
+
*/
|
|
6341
|
+
/**
|
|
6342
|
+
* Combined provider for grid type defaults and icons.
|
|
6343
|
+
*
|
|
6344
|
+
* Returns environment providers that can be added to your `ApplicationConfig`
|
|
6345
|
+
* `providers` array. Either field is optional — only the registries you
|
|
6346
|
+
* supply are wired up.
|
|
6347
|
+
*
|
|
6348
|
+
* Equivalent to calling `provideGridTypeDefaults(options.typeDefaults)` and
|
|
6349
|
+
* `provideGridIcons(options.icons)` separately.
|
|
6350
|
+
* @since 1.4.0
|
|
6351
|
+
*/
|
|
6352
|
+
function provideGrid(options = {}) {
|
|
6353
|
+
const providers = [];
|
|
6354
|
+
if (options.typeDefaults) {
|
|
6355
|
+
providers.push(provideGridTypeDefaults(options.typeDefaults));
|
|
6356
|
+
}
|
|
6357
|
+
if (options.icons) {
|
|
6358
|
+
providers.push(provideGridIcons(options.icons));
|
|
6359
|
+
}
|
|
6360
|
+
return makeEnvironmentProviders(providers);
|
|
6361
|
+
}
|
|
5815
6362
|
|
|
5816
6363
|
/**
|
|
5817
6364
|
* @packageDocumentation
|
|
@@ -5825,5 +6372,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
5825
6372
|
* Generated bundle index. Do not edit.
|
|
5826
6373
|
*/
|
|
5827
6374
|
|
|
5828
|
-
export { BaseFilterPanel, BaseGridEditor, BaseGridEditorCVA, BaseOverlayEditor, GRID_ICONS, GRID_TYPE_DEFAULTS, Grid, GridAdapter, GridColumnEditor, GridColumnView, GridDetailView, GridFormArray, GridIconRegistry, GridLazyForm, GridResponsiveCard, GridToolPanel, GridTypeRegistry, TbwEditor, TbwGridColumn, TbwGridHeader, TbwGridToolButtons, TbwRenderer, getFormArrayContext, getLazyFormContext, injectGrid, isComponentClass, provideGridIcons, provideGridTypeDefaults };
|
|
6375
|
+
export { BaseFilterPanel, BaseGridEditor, BaseGridEditorCVA, BaseOverlayEditor, GRID_ICONS, GRID_TYPE_DEFAULTS, Grid, GridAdapter, GridColumnEditor, GridColumnView, GridDetailView, GridFormArray, GridIconRegistry, GridLazyForm, GridResponsiveCard, GridToolPanel, GridTypeRegistry, TbwEditor, TbwGridColumn, TbwGridHeader, TbwGridToolButtons, TbwRenderer, applyColumnDefaults, claimEvent, getDetailTemplate, getFeatureClaim, getFeatureConfigPreprocessor, getFormArrayContext, getLazyFormContext, getResponsiveCardTemplate, hasColumnShorthands, injectGrid, isComponentClass, isEventClaimed, makeFlushFocusedInput, normalizeColumns, parseColumnShorthand, provideGrid, provideGridIcons, provideGridTypeDefaults, registerDetailRendererBridge, registerEditorMountHook, registerFeatureClaim, registerFeatureConfigPreprocessor, registerFilterPanelTypeDefaultBridge, registerResponsiveCardRendererBridge, registerTemplateBridge, runTemplateBridges, unclaimEvent, unregisterFeatureClaim };
|
|
5829
6376
|
//# sourceMappingURL=toolbox-web-grid-angular.mjs.map
|