@toolbox-web/grid-angular 0.9.0 → 0.10.0

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.
@@ -1,6 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, contentChild, TemplateRef, effect, Directive, input, InjectionToken, Injectable, makeEnvironmentProviders, EventEmitter, createComponent, signal, afterNextRender, computed, output, EnvironmentInjector, ApplicationRef, ViewContainerRef } from '@angular/core';
2
+ import { inject, ElementRef, contentChild, TemplateRef, effect, Directive, input, DestroyRef, InjectionToken, Injectable, makeEnvironmentProviders, EventEmitter, createComponent, signal, afterNextRender, computed, output, EnvironmentInjector, ApplicationRef, ViewContainerRef } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
4
  import { FormGroup } from '@angular/forms';
5
+ import { startWith } from 'rxjs/operators';
4
6
  import { DataGridElement } from '@toolbox-web/grid';
5
7
 
6
8
  /**
@@ -339,10 +341,12 @@ function getFormArrayContext(gridElement) {
339
341
  * - Automatically syncs FormArray changes to the grid
340
342
  */
341
343
  class GridFormArray {
344
+ destroyRef = inject(DestroyRef);
342
345
  elementRef = inject((ElementRef));
343
346
  cellCommitListener = null;
344
347
  rowCommitListener = null;
345
348
  touchListener = null;
349
+ valueChangesSubscription = null;
346
350
  /**
347
351
  * The FormArray to bind to the grid.
348
352
  */
@@ -359,15 +363,24 @@ class GridFormArray {
359
363
  */
360
364
  syncValidation = input(true, ...(ngDevMode ? [{ debugName: "syncValidation" }] : []));
361
365
  /**
362
- * Effect that syncs the FormArray value to the grid rows.
366
+ * Effect that sets up valueChanges subscription when FormArray changes.
367
+ * This handles both initial binding and when the FormArray reference changes.
363
368
  */
364
369
  syncFormArrayToGrid = effect(() => {
365
370
  const formArray = this.formArray();
366
371
  const grid = this.elementRef.nativeElement;
367
- if (grid && formArray) {
368
- // Get the raw value (including disabled controls)
372
+ if (!grid || !formArray)
373
+ return;
374
+ // Unsubscribe from previous FormArray if any
375
+ this.valueChangesSubscription?.unsubscribe();
376
+ // Subscribe to valueChanges to sync grid rows when FormArray content changes.
377
+ // Use startWith to immediately sync the current value.
378
+ // Note: We use getRawValue() to include disabled controls.
379
+ this.valueChangesSubscription = formArray.valueChanges
380
+ .pipe(startWith(formArray.getRawValue()), takeUntilDestroyed(this.destroyRef))
381
+ .subscribe(() => {
369
382
  grid.rows = formArray.getRawValue();
370
- }
383
+ });
371
384
  }, ...(ngDevMode ? [{ debugName: "syncFormArrayToGrid" }] : []));
372
385
  ngOnInit() {
373
386
  const grid = this.elementRef.nativeElement;
@@ -413,6 +426,9 @@ class GridFormArray {
413
426
  if (this.touchListener) {
414
427
  grid.removeEventListener('click', this.touchListener);
415
428
  }
429
+ if (this.valueChangesSubscription) {
430
+ this.valueChangesSubscription.unsubscribe();
431
+ }
416
432
  this.#clearFormContext(grid);
417
433
  }
418
434
  /**
@@ -1268,14 +1284,39 @@ class AngularGridAdapter {
1268
1284
  * @returns Processed GridConfig with actual renderer/editor functions
1269
1285
  */
1270
1286
  processGridConfig(config) {
1271
- if (!config.columns) {
1272
- return config;
1287
+ const result = { ...config };
1288
+ // Process columns
1289
+ if (config.columns) {
1290
+ result.columns = config.columns.map((col) => this.processColumn(col));
1273
1291
  }
1274
- const processedColumns = config.columns.map((col) => this.processColumn(col));
1275
- return {
1276
- ...config,
1277
- columns: processedColumns,
1278
- };
1292
+ // Process typeDefaults - convert Angular component classes to renderer/editor functions
1293
+ if (config.typeDefaults) {
1294
+ result.typeDefaults = this.processTypeDefaults(config.typeDefaults);
1295
+ }
1296
+ return result;
1297
+ }
1298
+ /**
1299
+ * Processes typeDefaults configuration, converting component class references
1300
+ * to actual renderer/editor functions.
1301
+ *
1302
+ * @param typeDefaults - Angular type defaults with possible component class references
1303
+ * @returns Processed TypeDefault record
1304
+ */
1305
+ processTypeDefaults(typeDefaults) {
1306
+ const processed = {};
1307
+ for (const [type, config] of Object.entries(typeDefaults)) {
1308
+ const processedConfig = { ...config };
1309
+ // Convert renderer component class to function
1310
+ if (config.renderer && isComponentClass(config.renderer)) {
1311
+ processedConfig.renderer = this.createComponentRenderer(config.renderer);
1312
+ }
1313
+ // Convert editor component class to function
1314
+ if (config.editor && isComponentClass(config.editor)) {
1315
+ processedConfig.editor = this.createComponentEditor(config.editor);
1316
+ }
1317
+ processed[type] = processedConfig;
1318
+ }
1319
+ return processed;
1279
1320
  }
1280
1321
  /**
1281
1322
  * Processes a single column configuration, converting component class references
@@ -1318,6 +1359,11 @@ class AngularGridAdapter {
1318
1359
  return undefined;
1319
1360
  }
1320
1361
  return (ctx) => {
1362
+ // Skip rendering if the cell is in editing mode
1363
+ // This prevents the renderer from overwriting the editor when the grid re-renders
1364
+ if (ctx.cellEl?.classList.contains('editing')) {
1365
+ return null;
1366
+ }
1321
1367
  // Create the context for the template
1322
1368
  const context = {
1323
1369
  $implicit: ctx.value,
@@ -1358,10 +1404,10 @@ class AngularGridAdapter {
1358
1404
  // Find the parent grid element for FormArray context access
1359
1405
  const gridElement = element.closest('tbw-grid');
1360
1406
  if (!template) {
1361
- // No warning - this can happen during early initialization before Angular
1362
- // registers structural directive templates. The grid will re-parse columns
1363
- // after templates are registered.
1364
- return () => document.createElement('div');
1407
+ // No template registered - return undefined to let the grid use its default editor.
1408
+ // This allows columns with only *tbwRenderer (no *tbwEditor) to still be editable
1409
+ // using the built-in text/number/boolean editors.
1410
+ return undefined;
1365
1411
  }
1366
1412
  return (ctx) => {
1367
1413
  // Create simple callback functions (preferred)
@@ -1591,31 +1637,58 @@ class AngularGridAdapter {
1591
1637
  }
1592
1638
  return typeDefault;
1593
1639
  }
1640
+ /**
1641
+ * Creates and mounts an Angular component dynamically.
1642
+ * Shared logic between renderer and editor component creation.
1643
+ * @internal
1644
+ */
1645
+ mountComponent(componentClass, inputs) {
1646
+ // Create a host element for the component
1647
+ const hostElement = document.createElement('span');
1648
+ hostElement.style.display = 'contents';
1649
+ // Create the component dynamically
1650
+ const componentRef = createComponent(componentClass, {
1651
+ environmentInjector: this.injector,
1652
+ hostElement,
1653
+ });
1654
+ // Set inputs - components should have value, row, column inputs
1655
+ this.setComponentInputs(componentRef, inputs);
1656
+ // Attach to app for change detection
1657
+ this.appRef.attachView(componentRef.hostView);
1658
+ this.componentRefs.push(componentRef);
1659
+ // Trigger change detection
1660
+ componentRef.changeDetectorRef.detectChanges();
1661
+ return { hostElement, componentRef };
1662
+ }
1663
+ /**
1664
+ * Wires up commit/cancel handlers for an editor component.
1665
+ * Supports both Angular outputs and DOM CustomEvents.
1666
+ * @internal
1667
+ */
1668
+ wireEditorCallbacks(hostElement, componentRef, commit, cancel) {
1669
+ // Subscribe to Angular outputs (commit/cancel) on the component instance.
1670
+ // This works with Angular's output() signal API.
1671
+ const instance = componentRef.instance;
1672
+ this.subscribeToOutput(instance, 'commit', commit);
1673
+ this.subscribeToOutput(instance, 'cancel', cancel);
1674
+ // Also listen for DOM events as fallback (for components that dispatch CustomEvents)
1675
+ hostElement.addEventListener('commit', (e) => {
1676
+ const customEvent = e;
1677
+ commit(customEvent.detail);
1678
+ });
1679
+ hostElement.addEventListener('cancel', () => cancel());
1680
+ }
1594
1681
  /**
1595
1682
  * Creates a renderer function from an Angular component class.
1596
1683
  * @internal
1597
1684
  */
1598
1685
  createComponentRenderer(componentClass) {
1599
1686
  return (ctx) => {
1600
- // Create a host element for the component
1601
- const hostElement = document.createElement('span');
1602
- hostElement.style.display = 'contents';
1603
- // Create the component dynamically
1604
- const componentRef = createComponent(componentClass, {
1605
- environmentInjector: this.injector,
1606
- hostElement,
1607
- });
1608
- // Set inputs - components should have value, row, column inputs
1609
- this.setComponentInputs(componentRef, {
1687
+ const { hostElement } = this.mountComponent(componentClass, {
1610
1688
  value: ctx.value,
1611
1689
  row: ctx.row,
1612
1690
  column: ctx.column,
1613
1691
  });
1614
- // Attach to app for change detection
1615
- this.appRef.attachView(componentRef.hostView);
1616
- this.componentRefs.push(componentRef);
1617
- // Trigger change detection
1618
- componentRef.changeDetectorRef.detectChanges();
1619
1692
  return hostElement;
1620
1693
  };
1621
1694
  }
@@ -1625,38 +1698,12 @@ class AngularGridAdapter {
1625
1698
  */
1626
1699
  createComponentEditor(componentClass) {
1627
1700
  return (ctx) => {
1628
- // Create a host element for the component
1629
- const hostElement = document.createElement('span');
1630
- hostElement.style.display = 'contents';
1631
- // Create the component dynamically
1632
- const componentRef = createComponent(componentClass, {
1633
- environmentInjector: this.injector,
1634
- hostElement,
1635
- });
1636
- // Set inputs - components should have value, row, column inputs
1637
- this.setComponentInputs(componentRef, {
1701
+ const { hostElement, componentRef } = this.mountComponent(componentClass, {
1638
1702
  value: ctx.value,
1639
1703
  row: ctx.row,
1640
1704
  column: ctx.column,
1641
1705
  });
1642
- // Attach to app for change detection
1643
- this.appRef.attachView(componentRef.hostView);
1644
- this.componentRefs.push(componentRef);
1645
- // Trigger change detection
1646
- componentRef.changeDetectorRef.detectChanges();
1647
- // Subscribe to Angular outputs (commit/cancel) on the component instance.
1648
- // This works with Angular's output() signal API.
1649
- const instance = componentRef.instance;
1650
- this.subscribeToOutput(instance, 'commit', (value) => ctx.commit(value));
1651
- this.subscribeToOutput(instance, 'cancel', () => ctx.cancel());
1652
- // Also listen for DOM events as fallback (for components that dispatch CustomEvents)
1653
- hostElement.addEventListener('commit', (e) => {
1654
- const customEvent = e;
1655
- ctx.commit(customEvent.detail);
1656
- });
1657
- hostElement.addEventListener('cancel', () => {
1658
- ctx.cancel();
1659
- });
1706
+ this.wireEditorCallbacks(hostElement, componentRef, (value) => ctx.commit(value), () => ctx.cancel());
1660
1707
  return hostElement;
1661
1708
  };
1662
1709
  }
@@ -2423,16 +2470,12 @@ class Grid {
2423
2470
  // Effect to process angularConfig and apply to grid
2424
2471
  // This merges feature input plugins with the user's config plugins
2425
2472
  effect(() => {
2426
- const config = this.angularConfig();
2473
+ const angularCfg = this.angularConfig();
2474
+ const userGridConfig = this.gridConfig();
2427
2475
  if (!this.adapter)
2428
2476
  return;
2429
- // Process the config to convert component classes to actual renderer/editor functions
2430
- const processedConfig = config ? this.adapter.processGridConfig(config) : {};
2431
- // Create plugins from feature inputs and merge with config plugins
2477
+ // Create plugins from feature inputs
2432
2478
  const featurePlugins = this.createFeaturePlugins();
2433
- const configPlugins = processedConfig.plugins || [];
2434
- // Merge: feature plugins first, then config plugins
2435
- const mergedPlugins = [...featurePlugins, ...configPlugins];
2436
2479
  // Build core config overrides from individual inputs
2437
2480
  const sortableValue = this.sortable();
2438
2481
  const filterableValue = this.filterable();
@@ -2447,19 +2490,39 @@ class Grid {
2447
2490
  if (selectableValue !== undefined) {
2448
2491
  coreConfigOverrides['selectable'] = selectableValue;
2449
2492
  }
2450
- // Merge icon overrides from registry with any existing icons in config
2493
+ const grid = this.elementRef.nativeElement;
2494
+ // Merge icon overrides from registry with any existing icons
2451
2495
  // Registry icons are base, config.icons override them
2452
2496
  const registryIcons = this.iconRegistry?.getAll();
2453
2497
  if (registryIcons && Object.keys(registryIcons).length > 0) {
2454
- const existingIcons = processedConfig?.icons || config?.icons || {};
2498
+ const existingIcons = angularCfg?.icons || userGridConfig?.icons || {};
2455
2499
  coreConfigOverrides['icons'] = { ...registryIcons, ...existingIcons };
2456
2500
  }
2457
- // Apply to the grid element
2458
- const grid = this.elementRef.nativeElement;
2501
+ // If angularConfig is provided, process it (converts component classes to renderer functions)
2502
+ const processedConfig = angularCfg ? this.adapter.processGridConfig(angularCfg) : null;
2503
+ // IMPORTANT: If user is NOT using angularConfig input, and there are no feature plugins
2504
+ // or config overrides to merge, do NOT overwrite grid.gridConfig.
2505
+ // This allows [gridConfig]="myConfig" binding to work correctly without the directive
2506
+ // creating a new object that strips properties like typeDefaults.
2507
+ const hasFeaturePlugins = featurePlugins.length > 0;
2508
+ const hasConfigOverrides = Object.keys(coreConfigOverrides).length > 0;
2509
+ // Use the gridConfig input signal (preferred) or fallback to what's on the grid element
2510
+ // The input signal gives us reactive tracking of the user's config
2511
+ const existingConfig = userGridConfig || {};
2512
+ if (!processedConfig && !hasFeaturePlugins && !hasConfigOverrides && !userGridConfig) {
2513
+ // Nothing to merge and no config input - let the user's DOM binding work directly
2514
+ return;
2515
+ }
2516
+ // Merge: existing config (from [gridConfig] input) < processed angularConfig < feature plugins
2517
+ const configPlugins = processedConfig?.plugins || existingConfig.plugins || [];
2518
+ const mergedPlugins = [...featurePlugins, ...configPlugins];
2519
+ // Build the final config, preserving ALL existing properties (including typeDefaults)
2520
+ const baseConfig = processedConfig || existingConfig;
2459
2521
  grid.gridConfig = {
2460
- ...processedConfig,
2522
+ ...existingConfig, // Start with existing config to preserve all properties (including typeDefaults)
2523
+ ...baseConfig, // Then apply processed/angular config
2461
2524
  ...coreConfigOverrides,
2462
- plugins: mergedPlugins.length > 0 ? mergedPlugins : undefined,
2525
+ plugins: mergedPlugins.length > 0 ? mergedPlugins : baseConfig.plugins,
2463
2526
  };
2464
2527
  });
2465
2528
  // Effect to sync loading state to the grid element
@@ -2578,6 +2641,33 @@ class Grid {
2578
2641
  * ```
2579
2642
  */
2580
2643
  loading = input(...(ngDevMode ? [undefined, { debugName: "loading" }] : []));
2644
+ /**
2645
+ * Core grid configuration object.
2646
+ *
2647
+ * Use this input for the base GridConfig (typeDefaults, getRowId, etc.).
2648
+ * This is the same as binding directly to the web component's gridConfig property,
2649
+ * but allows the directive to properly merge feature plugins and config overrides.
2650
+ *
2651
+ * For Angular-specific features (component class renderers/editors), use `angularConfig` instead.
2652
+ *
2653
+ * @example
2654
+ * ```typescript
2655
+ * config: GridConfig = {
2656
+ * typeDefaults: {
2657
+ * boolean: { renderer: (ctx) => ctx.value ? '✓' : '✗' }
2658
+ * }
2659
+ * };
2660
+ * columns = [
2661
+ * { field: 'active', type: 'boolean' }
2662
+ * ];
2663
+ * ```
2664
+ *
2665
+ * ```html
2666
+ * <tbw-grid [gridConfig]="config" [columns]="columns" />
2667
+ * ```
2668
+ */
2669
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2670
+ gridConfig = input(...(ngDevMode ? [undefined, { debugName: "gridConfig" }] : []));
2581
2671
  /**
2582
2672
  * Angular-specific grid configuration that supports component classes for renderers/editors.
2583
2673
  *
@@ -2654,6 +2744,9 @@ class Grid {
2654
2744
  * <tbw-grid [editing]="'click'" />
2655
2745
  * <tbw-grid [editing]="'dblclick'" />
2656
2746
  * <tbw-grid [editing]="'manual'" />
2747
+ *
2748
+ * <!-- Full config with callbacks -->
2749
+ * <tbw-grid [editing]="{ editOn: 'dblclick', onBeforeEditClose: myCallback }" />
2657
2750
  * ```
2658
2751
  */
2659
2752
  editing = input(...(ngDevMode ? [undefined, { debugName: "editing" }] : []));
@@ -3442,12 +3535,12 @@ class Grid {
3442
3535
  }
3443
3536
  }
3444
3537
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: Grid, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3445
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", 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 }, angularConfig: { classPropertyName: "angularConfig", publicName: "angularConfig", 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 }, sorting: { classPropertyName: "sorting", publicName: "sorting", isSignal: true, isRequired: false, transformFunction: null }, filtering: { classPropertyName: "filtering", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, reorder: { classPropertyName: "reorder", publicName: "reorder", 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 }, rowReorder: { classPropertyName: "rowReorder", publicName: "rowReorder", 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: "exportFeature", 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 } }, 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", groupToggle: "groupToggle", treeExpand: "treeExpand", detailExpand: "detailExpand", responsiveChange: "responsiveChange", copy: "copy", paste: "paste", undoRedoAction: "undoRedoAction", exportComplete: "exportComplete", printStart: "printStart", printComplete: "printComplete" }, ngImport: i0 });
3538
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", 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 }, gridConfig: { classPropertyName: "gridConfig", publicName: "gridConfig", isSignal: true, isRequired: false, transformFunction: null }, angularConfig: { classPropertyName: "angularConfig", publicName: "angularConfig", 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 }, sorting: { classPropertyName: "sorting", publicName: "sorting", isSignal: true, isRequired: false, transformFunction: null }, filtering: { classPropertyName: "filtering", publicName: "filtering", isSignal: true, isRequired: false, transformFunction: null }, reorder: { classPropertyName: "reorder", publicName: "reorder", 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 }, rowReorder: { classPropertyName: "rowReorder", publicName: "rowReorder", 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: "exportFeature", 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 } }, 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", groupToggle: "groupToggle", treeExpand: "treeExpand", detailExpand: "detailExpand", responsiveChange: "responsiveChange", copy: "copy", paste: "paste", undoRedoAction: "undoRedoAction", exportComplete: "exportComplete", printStart: "printStart", printComplete: "printComplete" }, ngImport: i0 });
3446
3539
  }
3447
3540
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: Grid, decorators: [{
3448
3541
  type: Directive,
3449
3542
  args: [{ selector: 'tbw-grid' }]
3450
- }], 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 }] }], angularConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "angularConfig", 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 }] }], sorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "sorting", required: false }] }], filtering: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], reorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorder", 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 }] }], rowReorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowReorder", 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: "exportFeature", 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 }] }], 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"] }], 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"] }], undoRedoAction: [{ type: i0.Output, args: ["undoRedoAction"] }], exportComplete: [{ type: i0.Output, args: ["exportComplete"] }], printStart: [{ type: i0.Output, args: ["printStart"] }], printComplete: [{ type: i0.Output, args: ["printComplete"] }] } });
3543
+ }], 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 }] }], gridConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridConfig", required: false }] }], angularConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "angularConfig", 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 }] }], sorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "sorting", required: false }] }], filtering: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtering", required: false }] }], reorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorder", 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 }] }], rowReorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowReorder", 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: "exportFeature", 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 }] }], 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"] }], 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"] }], undoRedoAction: [{ type: i0.Output, args: ["undoRedoAction"] }], exportComplete: [{ type: i0.Output, args: ["exportComplete"] }], printStart: [{ type: i0.Output, args: ["printStart"] }], printComplete: [{ type: i0.Output, args: ["printComplete"] }] } });
3451
3544
 
3452
3545
  /**
3453
3546
  * @packageDocumentation