@progress/kendo-angular-grid 19.2.0-develop.14 → 19.2.0-develop.3

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 CHANGED
@@ -4,14 +4,9 @@
4
4
 
5
5
  ## Kendo UI for Angular Data Grid Component
6
6
 
7
- > * This package is part of [Kendo UI for Angular](https://www.telerik.com/kendo-angular-ui/)—a commercial UI library.
8
- > * To use this package, you must install a license key file, whether you are on a paid license or a 30-day free trial. To receive a license key, either [purchase a license](https://www.telerik.com/purchase/kendo-ui) or start a [free trial](https://www.telerik.com/download-login-v2-kendo-angular-ui).
9
- > * Adding a valid license key file ensures a seamless experience during the trial period—no watermarks, no warnings, and full access to all components and features.
10
- > * Trial users can register for a free license key file. Without it, your trial may be interrupted by visual indicators or functionality limitations.
11
- > * Additionally, for the period of your license, you get access to our legendary technical support provided directly by the Kendo UI for Angular team!
12
- > * Learn more: https://www.telerik.com/kendo-angular-ui/components/licensing
13
- >
14
- > [Start using Kendo UI for Angular](https://www.telerik.com/download-login-v2-kendo-angular-ui) and speed up your development process!
7
+ > * This package is part of the [Kendo UI for Angular](https://www.telerik.com/kendo-angular-ui/)—a commercial UI library.
8
+ > * You must [install a license key](https://www.telerik.com/kendo-angular-ui/my-license) when adding the package to your project. To receive a license key, either [purchase a license](https://www.telerik.com/purchase/kendo-ui) or register for a [free trial](https://www.telerik.com/download-login-v2-kendo-angular-ui).
9
+ > * The 30-day free trial gives you access to all the Kendo UI for Angular components and their full functionality. Additionally, for the period of your license, you get access to our legendary technical support provided directly by the Kendo UI for Angular team!
15
10
 
16
11
  The [Kendo UI for Angular Data Grid](https://www.telerik.com/kendo-angular-ui/components/grid) includes a comprehensive set of ready-to-use features covering everything from paging, sorting, filtering, editing, and grouping to row and column virtualization, exporting to PDF and Excel, and accessibility support. This Data Grid Component (sometimes called a Data Table) is built on Angular from the ground up, by a company with a long history of making enterprise-ready Grids. This results in an Angular data grid that delivers lighting fast performance and is highly customizable.
17
12
 
@@ -7,6 +7,7 @@ import { CellSelectionItem, SelectionEvent } from '../selection/types';
7
7
  import { RowArgs } from '../rendering/common/row-args';
8
8
  import { ContextService } from '../common/provider.service';
9
9
  import { ColumnInfoService } from '../common/column-info.service';
10
+ import { LocalDataChangesService } from '../editing/local-data-changes.service';
10
11
  import * as i0 from "@angular/core";
11
12
  /**
12
13
  * @hidden
@@ -21,12 +22,13 @@ interface GroupedAggregates {
21
22
  */
22
23
  export declare class CellSelectionAggregateService {
23
24
  private ctx;
25
+ private dataChanges;
24
26
  private columnInfoService;
25
27
  selectedItems: Array<CellSelectionItem | RowArgs>;
26
28
  groupedAggregates: GroupedAggregates;
27
29
  aggregates: SelectionAggregates;
28
30
  private sub;
29
- constructor(ctx: ContextService, columnInfoService: ColumnInfoService);
31
+ constructor(ctx: ContextService, dataChanges: LocalDataChangesService, columnInfoService: ColumnInfoService);
30
32
  ngOnDestroy(): void;
31
33
  isAggregateIncluded(aggregate: SelectionAggregate): boolean;
32
34
  init(): void;
@@ -6,7 +6,7 @@ import { ChangeDetectorRef, ElementRef, NgZone, Renderer2 } from '@angular/core'
6
6
  import { ContextService } from '../common/provider.service';
7
7
  import * as i0 from "@angular/core";
8
8
  /**
9
- * Represents a directive that manages keyboard navigation for a column menu item ([see example](slug:columnmenu_grid#customizing-the-content)).
9
+ * Represents a directive that manages keyboard navigation for a column menu item. [See example](slug:columnmenu_grid#customizing-the-content).
10
10
  *
11
11
  * @example
12
12
  * ```html
@@ -7,7 +7,6 @@ import { LocalizationService } from '@progress/kendo-angular-l10n';
7
7
  import type { GridComponent } from '../grid.component';
8
8
  import { GridToolbarNavigationService } from '../rendering/toolbar/toolbar-navigation.service';
9
9
  import type { GroupBindingDirective } from '../grouping/group-scroll-binding.directive';
10
- import type { DataBindingDirective } from '../databinding.directive';
11
10
  import * as i0 from "@angular/core";
12
11
  /**
13
12
  * @hidden
@@ -25,7 +24,7 @@ export declare class ContextService {
25
24
  topToolbarNavigation: GridToolbarNavigationService;
26
25
  bottomToolbarNavigation: GridToolbarNavigationService;
27
26
  navigable: boolean;
28
- dataBindingDirective: DataBindingDirective | GroupBindingDirective;
27
+ groupBindingDirective: GroupBindingDirective;
29
28
  constructor(renderer: Renderer2, localization: LocalizationService);
30
29
  static ɵfac: i0.ɵɵFactoryDeclaration<ContextService, never>;
31
30
  static ɵprov: i0.ɵɵInjectableDeclaration<ContextService>;
@@ -10,7 +10,6 @@ import { GridDataResult } from './data/data.collection';
10
10
  import { LocalDataChangesService } from './editing/local-data-changes.service';
11
11
  import { RowReorderEvent } from './row-reordering/types';
12
12
  import { RowReorderService } from './row-reordering/row-reorder.service';
13
- import { ContextService } from './common/provider.service';
14
13
  import * as i0 from "@angular/core";
15
14
  /**
16
15
  * A directive that handles in-memory data operations like [paging]({% slug paging_grid %}),
@@ -68,7 +67,7 @@ export declare class DataBindingDirective implements OnInit, OnDestroy, DoCheck,
68
67
  private stateChangeSubscription;
69
68
  private dataChangedSubscription;
70
69
  private rowReorderSubscription;
71
- constructor(grid: GridComponent, changeDetector?: ChangeDetectorRef, localDataChangesService?: LocalDataChangesService, rowReorderService?: RowReorderService, ctx?: ContextService);
70
+ constructor(grid: GridComponent, changeDetector?: ChangeDetectorRef, localDataChangesService?: LocalDataChangesService, rowReorderService?: RowReorderService);
72
71
  /**
73
72
  * @hidden
74
73
  */
@@ -5,16 +5,19 @@
5
5
  import { Injectable } from '@angular/core';
6
6
  import { ContextService } from '../common/provider.service';
7
7
  import { ColumnInfoService } from '../common/column-info.service';
8
+ import { LocalDataChangesService } from '../editing/local-data-changes.service';
8
9
  import { recursiveFlatMap } from '../utils';
9
10
  import { Subscription } from 'rxjs';
10
11
  import * as i0 from "@angular/core";
11
12
  import * as i1 from "../common/provider.service";
12
- import * as i2 from "../common/column-info.service";
13
+ import * as i2 from "../editing/local-data-changes.service";
14
+ import * as i3 from "../common/column-info.service";
13
15
  /**
14
16
  * @hidden
15
17
  */
16
18
  export class CellSelectionAggregateService {
17
19
  ctx;
20
+ dataChanges;
18
21
  columnInfoService;
19
22
  selectedItems = [];
20
23
  groupedAggregates = { dates: [], numbers: [], booleans: [] };
@@ -30,8 +33,9 @@ export class CellSelectionAggregateService {
30
33
  latest: null
31
34
  };
32
35
  sub = new Subscription();
33
- constructor(ctx, columnInfoService) {
36
+ constructor(ctx, dataChanges, columnInfoService) {
34
37
  this.ctx = ctx;
38
+ this.dataChanges = dataChanges;
35
39
  this.columnInfoService = columnInfoService;
36
40
  }
37
41
  ngOnDestroy() {
@@ -192,9 +196,9 @@ export class CellSelectionAggregateService {
192
196
  this.aggregates['isFalse'] = this.aggregates['isTrue'] = null;
193
197
  this.aggregates['earliest'] = this.aggregates['latest'] = null;
194
198
  }
195
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, deps: [{ token: i1.ContextService }, { token: i2.ColumnInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
199
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, deps: [{ token: i1.ContextService }, { token: i2.LocalDataChangesService }, { token: i3.ColumnInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
196
200
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService });
197
201
  }
198
202
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, decorators: [{
199
203
  type: Injectable
200
- }], ctorParameters: function () { return [{ type: i1.ContextService }, { type: i2.ColumnInfoService }]; } });
204
+ }], ctorParameters: function () { return [{ type: i1.ContextService }, { type: i2.LocalDataChangesService }, { type: i3.ColumnInfoService }]; } });
@@ -12,7 +12,7 @@ import { ContextService } from '../common/provider.service';
12
12
  import * as i0 from "@angular/core";
13
13
  import * as i1 from "../common/provider.service";
14
14
  /**
15
- * Represents a directive that manages keyboard navigation for a column menu item ([see example](slug:columnmenu_grid#customizing-the-content)).
15
+ * Represents a directive that manages keyboard navigation for a column menu item. [See example](slug:columnmenu_grid#customizing-the-content).
16
16
  *
17
17
  * @example
18
18
  * ```html
@@ -23,7 +23,7 @@ export class ContextService {
23
23
  topToolbarNavigation;
24
24
  bottomToolbarNavigation;
25
25
  navigable;
26
- dataBindingDirective;
26
+ groupBindingDirective;
27
27
  constructor(renderer, localization) {
28
28
  this.renderer = renderer;
29
29
  this.localization = localization;
@@ -8,12 +8,10 @@ import { GridComponent } from './grid.component';
8
8
  import { anyChanged, isPresent } from './utils';
9
9
  import { LocalDataChangesService } from './editing/local-data-changes.service';
10
10
  import { RowReorderService } from './row-reordering/row-reorder.service';
11
- import { ContextService } from './common/provider.service';
12
11
  import * as i0 from "@angular/core";
13
12
  import * as i1 from "./grid.component";
14
13
  import * as i2 from "./editing/local-data-changes.service";
15
14
  import * as i3 from "./row-reordering/row-reorder.service";
16
- import * as i4 from "./common/provider.service";
17
15
  /**
18
16
  * A directive that handles in-memory data operations like [paging]({% slug paging_grid %}),
19
17
  * [sorting]({% slug sorting_grid %}), and [grouping]({% slug grouping_grid %}).
@@ -94,7 +92,7 @@ export class DataBindingDirective {
94
92
  stateChangeSubscription;
95
93
  dataChangedSubscription;
96
94
  rowReorderSubscription;
97
- constructor(grid, changeDetector, localDataChangesService, rowReorderService, ctx) {
95
+ constructor(grid, changeDetector, localDataChangesService, rowReorderService) {
98
96
  this.grid = grid;
99
97
  this.changeDetector = changeDetector;
100
98
  this.localDataChangesService = localDataChangesService;
@@ -102,7 +100,6 @@ export class DataBindingDirective {
102
100
  if (localDataChangesService) {
103
101
  this.dataChangedSubscription = this.localDataChangesService.changes.subscribe(this.rebind.bind(this));
104
102
  }
105
- ctx && (ctx.dataBindingDirective = this);
106
103
  }
107
104
  /**
108
105
  * @hidden
@@ -197,7 +194,7 @@ export class DataBindingDirective {
197
194
  this.grid.updateNavigationMetadata();
198
195
  this.dataChanged = false;
199
196
  }
200
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, deps: [{ token: i1.GridComponent }, { token: i0.ChangeDetectorRef }, { token: i2.LocalDataChangesService }, { token: i3.RowReorderService }, { token: i4.ContextService }], target: i0.ɵɵFactoryTarget.Directive });
197
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, deps: [{ token: i1.GridComponent }, { token: i0.ChangeDetectorRef }, { token: i2.LocalDataChangesService }, { token: i3.RowReorderService }], target: i0.ɵɵFactoryTarget.Directive });
201
198
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: DataBindingDirective, isStandalone: true, selector: "[kendoGridBinding]", inputs: { skip: "skip", sort: "sort", filter: "filter", pageSize: "pageSize", group: "group", data: ["kendoGridBinding", "data"] }, exportAs: ["kendoGridBinding"], usesOnChanges: true, ngImport: i0 });
202
199
  }
203
200
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, decorators: [{
@@ -207,7 +204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
207
204
  exportAs: 'kendoGridBinding',
208
205
  standalone: true
209
206
  }]
210
- }], ctorParameters: function () { return [{ type: i1.GridComponent }, { type: i0.ChangeDetectorRef }, { type: i2.LocalDataChangesService }, { type: i3.RowReorderService }, { type: i4.ContextService }]; }, propDecorators: { skip: [{
207
+ }], ctorParameters: function () { return [{ type: i1.GridComponent }, { type: i0.ChangeDetectorRef }, { type: i2.LocalDataChangesService }, { type: i3.RowReorderService }]; }, propDecorators: { skip: [{
211
208
  type: Input
212
209
  }], sort: [{
213
210
  type: Input
@@ -921,8 +921,10 @@ export class GridComponent {
921
921
  dragTargetContainer;
922
922
  dropTargetContainer;
923
923
  dialogContainer;
924
+ /**
925
+ * @hidden
926
+ */
924
927
  adaptiveRenderer;
925
- listComponent;
926
928
  get scrollbarWidth() {
927
929
  return this.supportService.scrollbarWidth;
928
930
  }
@@ -1607,12 +1609,12 @@ export class GridComponent {
1607
1609
  this.sort = state.sort;
1608
1610
  this.group = state.group;
1609
1611
  this.filter = state.filter;
1612
+ this.group = state.group;
1610
1613
  this.skip = state.skip;
1611
1614
  this.pageSize = state.take;
1612
- if (state.currentData) {
1613
- this.data = state.currentData;
1614
- }
1615
- this.changeDetectorRef.markForCheck();
1615
+ this.data = state.currentData;
1616
+ this.changeNotification.notify();
1617
+ this.changeDetectorRef.detectChanges();
1616
1618
  }
1617
1619
  traverseColumns(columns, callback) {
1618
1620
  columns.forEach((column) => {
@@ -1823,9 +1825,6 @@ export class GridComponent {
1823
1825
  source.locked = target.locked;
1824
1826
  }
1825
1827
  this.columnsContainer.refresh();
1826
- if (this.virtualColumns) {
1827
- this.listComponent.updateViewportColumns();
1828
- }
1829
1828
  this.changeDetectorRef.markForCheck();
1830
1829
  });
1831
1830
  }
@@ -2248,8 +2247,7 @@ export class GridComponent {
2248
2247
  column = toAdd.shift();
2249
2248
  viewportColumns.push(column);
2250
2249
  if (column.isColumnGroup) {
2251
- const children = columnsArray.filter(c => c.parent && c.parent.id === column.id);
2252
- toAdd.unshift(...children);
2250
+ toAdd.unshift(...column.childrenArray);
2253
2251
  }
2254
2252
  }
2255
2253
  const lastFromGroup = viewportColumns[viewportColumns.length - 1];
@@ -2305,8 +2303,8 @@ export class GridComponent {
2305
2303
  }
2306
2304
  if (this.groupsService.isExpanded({ groupIndex: index }) !== expand) {
2307
2305
  this.groupsService.toggleRow({ index }, false);
2308
- if (this.ctx.dataBindingDirective && isPresent(this.ctx.dataBindingDirective.groupExpand)) {
2309
- this.ctx.dataBindingDirective[`group${expand ? 'Expand' : 'Collapse'}`]({ groupIndex: index });
2306
+ if (this.ctx.groupBindingDirective) {
2307
+ this.ctx.groupBindingDirective[`group${expand ? 'Expand' : 'Collapse'}`]({ groupIndex: index });
2310
2308
  }
2311
2309
  }
2312
2310
  }
@@ -2379,7 +2377,7 @@ export class GridComponent {
2379
2377
  ColumnMenuService,
2380
2378
  MenuTabbingService,
2381
2379
  DataMappingService
2382
- ], queries: [{ propertyName: "columns", predicate: ColumnBase }, { propertyName: "detailTemplateChildren", predicate: DetailTemplateDirective }, { propertyName: "cellLoadingTemplateChildren", predicate: CellLoadingTemplateDirective }, { propertyName: "loadingTemplateChildren", predicate: LoadingTemplateDirective }, { propertyName: "statusBarTemplateChildren", predicate: StatusBarTemplateDirective }, { propertyName: "noRecordsTemplateChildren", predicate: NoRecordsTemplateDirective }, { propertyName: "pagerTemplateChildren", predicate: PagerTemplateDirective }, { propertyName: "toolbarTemplateChildren", predicate: ToolbarTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], viewQueries: [{ propertyName: "lockedHeader", first: true, predicate: ["lockedHeader"], descendants: true }, { propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "ariaRoot", first: true, predicate: ["ariaRoot"], descendants: true, static: true }, { propertyName: "dragTargetContainer", first: true, predicate: DragTargetContainerDirective, descendants: true }, { propertyName: "dropTargetContainer", first: true, predicate: DropTargetContainerDirective, descendants: true }, { propertyName: "dialogContainer", first: true, predicate: ["dialogContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "listComponent", first: true, predicate: ListComponent, descendants: true }, { propertyName: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
2380
+ ], queries: [{ propertyName: "columns", predicate: ColumnBase }, { propertyName: "detailTemplateChildren", predicate: DetailTemplateDirective }, { propertyName: "cellLoadingTemplateChildren", predicate: CellLoadingTemplateDirective }, { propertyName: "loadingTemplateChildren", predicate: LoadingTemplateDirective }, { propertyName: "statusBarTemplateChildren", predicate: StatusBarTemplateDirective }, { propertyName: "noRecordsTemplateChildren", predicate: NoRecordsTemplateDirective }, { propertyName: "pagerTemplateChildren", predicate: PagerTemplateDirective }, { propertyName: "toolbarTemplateChildren", predicate: ToolbarTemplateDirective }, { propertyName: "columnMenuTemplates", predicate: ColumnMenuTemplateDirective }], viewQueries: [{ propertyName: "lockedHeader", first: true, predicate: ["lockedHeader"], descendants: true }, { propertyName: "header", first: true, predicate: ["header"], descendants: true }, { propertyName: "ariaRoot", first: true, predicate: ["ariaRoot"], descendants: true, static: true }, { propertyName: "dragTargetContainer", first: true, predicate: DragTargetContainerDirective, descendants: true }, { propertyName: "dropTargetContainer", first: true, predicate: DropTargetContainerDirective, descendants: true }, { propertyName: "dialogContainer", first: true, predicate: ["dialogContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "adaptiveRenderer", first: true, predicate: AdaptiveRendererComponent, descendants: true }, { propertyName: "footer", predicate: ["footer"], descendants: true }], exportAs: ["kendoGrid"], usesOnChanges: true, ngImport: i0, template: `
2383
2381
  <ng-container kendoGridLocalizedMessages
2384
2382
  i18n-groupPanelEmpty="kendo.grid.groupPanelEmpty|The label visible in the Grid group panel when it is empty"
2385
2383
  groupPanelEmpty="Drag a column header and drop it here to group by that column"
@@ -4196,7 +4194,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
4196
4194
  }], adaptiveRenderer: [{
4197
4195
  type: ViewChild,
4198
4196
  args: [AdaptiveRendererComponent]
4199
- }], listComponent: [{
4200
- type: ViewChild,
4201
- args: [ListComponent]
4202
4197
  }] } });
@@ -196,9 +196,9 @@ export class GroupBindingDirective extends DataBindingDirective {
196
196
  groups;
197
197
  gridSubs = new Subscription();
198
198
  constructor(changeDetector, localDataChangesService, ctxService, groupsService) {
199
- super(ctxService.grid, changeDetector, localDataChangesService, null, ctxService);
199
+ super(ctxService.grid, changeDetector, localDataChangesService);
200
200
  this.groupsService = groupsService;
201
- ctxService.dataBindingDirective = this;
201
+ ctxService.groupBindingDirective = this;
202
202
  }
203
203
  ngOnInit() {
204
204
  super.ngOnInit();
@@ -284,12 +284,6 @@ export class GroupBindingDirective extends DataBindingDirective {
284
284
  this.grid.data = this.dataResult(this.state.skip, this.state.take);
285
285
  }
286
286
  process(state) {
287
- if (this.grid.isVirtual && (!isPresent(state.take) || state.take === 0)) {
288
- return {
289
- data: [],
290
- total: this.originalData?.length || 0
291
- };
292
- }
293
287
  if (state.group && state.group.length) {
294
288
  const groups = this.processGroups(state);
295
289
  this.grid.skip -= skippedHeaders(groups.data[0]);
@@ -10,7 +10,7 @@ export const packageMetadata = {
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCode: 'KENDOUIANGULAR',
12
12
  productCodes: ['KENDOUIANGULAR'],
13
- publishDate: 1751450548,
14
- version: '19.2.0-develop.14',
13
+ publishDate: 1750851099,
14
+ version: '19.2.0-develop.3',
15
15
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
16
16
  };
@@ -270,11 +270,10 @@ export class ListComponent {
270
270
  if (this.virtualColumns && (!this.viewportColumns || this.viewportWidthChange())) {
271
271
  this.updateViewportColumns();
272
272
  }
273
- const shouldCalculatePageSize = isDocumentAvailable() && this.isVirtual && this.ctx.grid && !this.ctx.grid.pageSize;
274
- if (shouldCalculatePageSize) {
273
+ if (this.isVirtual && this.ctx.grid && !this.ctx.grid.pageSize) {
275
274
  const calculatedPageSize = this.calcVirtualPageSize();
276
275
  if (calculatedPageSize > 0) {
277
- this.ngZone.onStable.pipe(take(1)).subscribe(() => {
276
+ this.ngZone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {
278
277
  this.ctx.grid.pageSize = calculatedPageSize;
279
278
  this.ngZone.run(() => {
280
279
  this.pageChange.emit({
@@ -353,36 +352,6 @@ export class ListComponent {
353
352
  args.preventDefault();
354
353
  }
355
354
  }
356
- updateViewportColumns(range) {
357
- const columns = this.columns.nonLockedLeafColumns.toArray();
358
- // eslint-disable-next-line prefer-const
359
- let { startIdx, endIdx, offset } = range || this.calculateViewportColumns();
360
- const start = Math.max(0, startIdx - bufferSize);
361
- const end = Math.min(endIdx + bufferSize, columns.length - 1);
362
- if (start < startIdx) {
363
- for (let idx = startIdx - 1; idx >= start; idx--) {
364
- offset -= columns[idx].width;
365
- }
366
- }
367
- let currentColumns = columns.slice(start, end + 1);
368
- this.viewportColumnsWidth = currentColumns.reduce((total, column) => total + column.width, 0);
369
- const stickyBeforeStart = columns.slice(0, start).filter(c => c.sticky && !currentColumns.some(col => col === c));
370
- const stickyAfterEnd = columns.slice(end, columns.length).filter(c => c.sticky && !currentColumns.some(col => col === c));
371
- currentColumns = [...stickyBeforeStart, ...currentColumns, ...stickyAfterEnd];
372
- if (start > 0) {
373
- const offsetColumn = new ColumnBase();
374
- offsetColumn.width = offset;
375
- currentColumns.unshift(offsetColumn);
376
- }
377
- this.viewportColumns = new QueryList();
378
- this.viewportColumns.reset(currentColumns);
379
- this.columnsStartIdx = start;
380
- this.columnsEndIdx = end;
381
- this.columnInfo.columnRangeChange.emit({ start, end, offset });
382
- if (!range) {
383
- this.updateColumnViewport(startIdx, endIdx);
384
- }
385
- }
386
355
  detailExpand({ index, expand }) {
387
356
  if (expand) {
388
357
  this.rowHeightService.expandDetail(index);
@@ -608,6 +577,36 @@ export class ListComponent {
608
577
  })
609
578
  .forEach(setHeight(this.renderer));
610
579
  }
580
+ updateViewportColumns(range) {
581
+ const columns = this.columns.nonLockedLeafColumns.toArray();
582
+ // eslint-disable-next-line prefer-const
583
+ let { startIdx, endIdx, offset } = range || this.calculateViewportColumns();
584
+ const start = Math.max(0, startIdx - bufferSize);
585
+ const end = Math.min(endIdx + bufferSize, columns.length - 1);
586
+ if (start < startIdx) {
587
+ for (let idx = startIdx - 1; idx >= start; idx--) {
588
+ offset -= columns[idx].width;
589
+ }
590
+ }
591
+ let currentColumns = columns.slice(start, end + 1);
592
+ this.viewportColumnsWidth = currentColumns.reduce((total, column) => total + column.width, 0);
593
+ const stickyBeforeStart = columns.slice(0, start).filter(c => c.sticky && !currentColumns.some(col => col === c));
594
+ const stickyAfterEnd = columns.slice(end, columns.length).filter(c => c.sticky && !currentColumns.some(col => col === c));
595
+ currentColumns = [...stickyBeforeStart, ...currentColumns, ...stickyAfterEnd];
596
+ if (start > 0) {
597
+ const offsetColumn = new ColumnBase();
598
+ offsetColumn.width = offset;
599
+ currentColumns.unshift(offsetColumn);
600
+ }
601
+ this.viewportColumns = new QueryList();
602
+ this.viewportColumns.reset(currentColumns);
603
+ this.columnsStartIdx = start;
604
+ this.columnsEndIdx = end;
605
+ this.columnInfo.columnRangeChange.emit({ start, end, offset });
606
+ if (!range) {
607
+ this.updateColumnViewport(startIdx, endIdx);
608
+ }
609
+ }
611
610
  handleColumnScroll() {
612
611
  const container = this.container.nativeElement;
613
612
  const scrollLeft = container.scrollLeft;
@@ -8,20 +8,15 @@ import { GridComponent } from '../grid.component';
8
8
  import { UndoRedoEvent } from './grid-state.models';
9
9
  import { Subscription } from 'rxjs';
10
10
  import { EditService } from '../editing/edit.service';
11
- import { filter } from 'rxjs/operators';
11
+ import { filter, tap } from 'rxjs/operators';
12
12
  import { UndoRedoService } from './undo-redo.service';
13
- import { hasObservers, isPresent } from '@progress/kendo-angular-common';
13
+ import { hasObservers } from '@progress/kendo-angular-common';
14
14
  import { ChangeNotificationService } from '../data/change-notification.service';
15
- import { ContextService } from '../common/provider.service';
16
- import { LocalDataChangesService } from '../editing/local-data-changes.service';
17
- import { recursiveFlatMap } from '../utils';
18
15
  import * as i0 from "@angular/core";
19
16
  import * as i1 from "../grid.component";
20
17
  import * as i2 from "../editing/edit.service";
21
18
  import * as i3 from "./undo-redo.service";
22
19
  import * as i4 from "../data/change-notification.service";
23
- import * as i5 from "../common/provider.service";
24
- import * as i6 from "../editing/local-data-changes.service";
25
20
  /**
26
21
  * Represents the directive that manages undo-redo operations in the Grid.
27
22
  * Use this directive to enable undo and redo functionality for user actions in the Grid.
@@ -38,17 +33,11 @@ export class UndoRedoDirective {
38
33
  editService;
39
34
  undoRedoService;
40
35
  changeNotification;
41
- ctx;
42
- localDataChangesService;
43
36
  /**
44
37
  * Sets the maximum number of actions to keep in the undo-redo stack.
45
38
  * @default 10
46
39
  */
47
40
  maxStoredStates = 10;
48
- /**
49
- * Defines the property name of the data item unique key that will be used to identify the items when performing undo-redo actions.
50
- */
51
- itemIdKey;
52
41
  /**
53
42
  * Fires when you perform the undo action. Provides the Grid state to apply.
54
43
  */
@@ -66,17 +55,24 @@ export class UndoRedoDirective {
66
55
  stack;
67
56
  subs = new Subscription();
68
57
  addToState = true;
69
- constructor(host, editService, undoRedoService, changeNotification, ctx, localDataChangesService) {
58
+ constructor(host, editService, undoRedoService, changeNotification) {
70
59
  this.host = host;
71
60
  this.editService = editService;
72
61
  this.undoRedoService = undoRedoService;
73
62
  this.changeNotification = changeNotification;
74
- this.ctx = ctx;
75
- this.localDataChangesService = localDataChangesService;
76
63
  this.host.undoRedoService = this.undoRedoService;
77
64
  }
78
65
  ngOnInit() {
79
66
  this.stack = new UndoRedoStack(this.maxStoredStates);
67
+ this.stack.add({
68
+ originalEvent: {
69
+ skip: this.host.skip,
70
+ take: this.host.pageSize,
71
+ sort: this.host.sort,
72
+ filter: this.host.filter,
73
+ group: this.host.group
74
+ }, gridState: structuredClone(this.host.currentState)
75
+ });
80
76
  this.subs = this.host.gridStateChange.subscribe((state) => {
81
77
  if (this.addToState) {
82
78
  this.stack.add({
@@ -87,7 +83,7 @@ export class UndoRedoDirective {
87
83
  filter: state.filter,
88
84
  group: state.group
89
85
  },
90
- gridState: state
86
+ gridState: structuredClone(state)
91
87
  });
92
88
  }
93
89
  let stackEndPointReached;
@@ -100,83 +96,36 @@ export class UndoRedoDirective {
100
96
  this.undoRedoService.stackEndReached.next(stackEndPointReached);
101
97
  });
102
98
  this.subs.add(this.editService.changes
103
- .pipe(filter((event) => event.action === 'save' || event.action === 'remove'))
99
+ .pipe(filter(event => event.action === 'save' || event.action === 'remove'), tap(event => this.undoRedoService.originalEvent = event))
104
100
  .subscribe(event => {
105
101
  this.stack.add({
106
- originalEvent: { ...event, dataItem: structuredClone(event.dataItem) },
107
- gridState: this.host.currentState
102
+ originalEvent: event,
103
+ gridState: structuredClone(this.host.currentState)
108
104
  });
109
105
  this.addToState = false;
110
106
  this.host.gridStateChange.emit(this.stack.current.gridState);
111
107
  this.addToState = true;
112
108
  this.updateUndoRedoDisabled();
113
109
  }));
114
- this.subs.add(this.changeNotification.changes.subscribe(() => {
115
- if (!this.ctx.dataBindingDirective) {
116
- this.stack.current.gridState = this.host.currentState;
117
- }
118
- }));
110
+ this.subs.add(this.changeNotification.changes.subscribe(() => this.stack.current.gridState = this.host.currentState));
119
111
  ['Undo', 'Redo'].forEach((action) => {
120
112
  this.subs.add(this.undoRedoService[`on${action}`].subscribe(() => {
121
113
  if (!this.stack[`can${action}`]) {
122
114
  return;
123
115
  }
124
- let eventData;
125
- if (action === 'Undo') {
126
- const isSaveOrRemove = this.stack.current.originalEvent.action === 'save' || this.stack.current.originalEvent.action === 'remove';
127
- eventData = isSaveOrRemove ? this.stack.current : this.stack.peekPrev();
128
- }
129
- else {
130
- eventData = this.stack.peekNext();
131
- }
132
- const event = new UndoRedoEvent(eventData);
116
+ this.stack[`${action.toLowerCase()}`]();
133
117
  if (hasObservers(this[`on${action}`])) {
118
+ const event = new UndoRedoEvent(this.stack.current);
134
119
  this[`on${action}`].emit(event);
135
120
  if (event.isDefaultPrevented()) {
136
121
  return;
137
122
  }
138
123
  }
139
- this.stack[`${action.toLowerCase()}`]();
140
124
  this.updateUndoRedoDisabled();
141
- const originalAction = event.originalEvent.action;
142
- const isLocalData = isPresent(this.ctx?.dataBindingDirective);
143
- if (!isLocalData) {
144
- return;
145
- }
146
- const isSaveOrRemove = originalAction === 'save' || originalAction === 'remove';
147
- if (isSaveOrRemove) {
148
- if (originalAction === 'save') {
149
- const stateItem = this.getGridDataItems(this.stack.current.gridState.currentData).find(item => item[this.itemIdKey] === event.originalEvent.dataItem[this.itemIdKey]);
150
- this.localDataChangesService?.data.splice(event.originalEvent.rowIndex, 1, stateItem);
151
- }
152
- else if (action === 'Undo') {
153
- this.localDataChangesService?.data.splice(event.originalEvent.rowIndex, 0, event.originalEvent.dataItem);
154
- }
155
- else {
156
- this.localDataChangesService?.data.splice(event.originalEvent.rowIndex, 1);
157
- }
158
- this.localDataChangesService?.changes.emit();
159
- }
160
- else {
161
- this.host.loadState({ ...this.stack.current.gridState, currentData: null });
162
- if (this.isDataStateChangeEvent(event.originalEvent)) {
163
- const { skip, take, sort, filter, group } = event.gridState;
164
- this.host.dataStateChange.emit({ skip, take, sort, filter, group });
165
- }
166
- }
125
+ this.host.loadState(this.stack.current.gridState);
167
126
  }));
168
127
  });
169
- }
170
- ngAfterViewInit() {
171
- this.stack.add({
172
- originalEvent: {
173
- skip: this.host.skip,
174
- take: this.host.pageSize,
175
- sort: this.host.sort,
176
- filter: this.host.filter,
177
- group: this.host.group
178
- }, gridState: this.host.currentState
179
- });
128
+ this.subs.add(this.undoRedoService.setState.subscribe((state) => this.stack.add({ originalEvent: 'dataChange', gridState: state })));
180
129
  }
181
130
  ngOnDestroy() {
182
131
  this.stack.clear();
@@ -218,15 +167,8 @@ export class UndoRedoDirective {
218
167
  }
219
168
  this.undoRedoService.stackEndReached.next(false);
220
169
  }
221
- getGridDataItems(data) {
222
- return Array.isArray(data) ? data.flatMap(recursiveFlatMap) :
223
- data.data.flatMap(recursiveFlatMap);
224
- }
225
- isDataStateChangeEvent(event) {
226
- return event && ['skip', 'take', 'sort', 'filter', 'group'].some(prop => prop in event);
227
- }
228
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, deps: [{ token: i1.GridComponent }, { token: i2.EditService }, { token: i3.UndoRedoService }, { token: i4.ChangeNotificationService }, { token: i5.ContextService }, { token: i6.LocalDataChangesService }], target: i0.ɵɵFactoryTarget.Directive });
229
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: UndoRedoDirective, isStandalone: true, selector: "[kendoGridUndoRedo]", inputs: { maxStoredStates: "maxStoredStates", itemIdKey: "itemIdKey" }, outputs: { onUndo: "undo", onRedo: "redo" }, providers: [UndoRedoService], exportAs: ["kendoGridUndoRedo"], ngImport: i0 });
170
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, deps: [{ token: i1.GridComponent }, { token: i2.EditService }, { token: i3.UndoRedoService }, { token: i4.ChangeNotificationService }], target: i0.ɵɵFactoryTarget.Directive });
171
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: UndoRedoDirective, isStandalone: true, selector: "[kendoGridUndoRedo]", inputs: { maxStoredStates: "maxStoredStates" }, outputs: { onUndo: "undo", onRedo: "redo" }, providers: [UndoRedoService], exportAs: ["kendoGridUndoRedo"], ngImport: i0 });
230
172
  }
231
173
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, decorators: [{
232
174
  type: Directive,
@@ -236,9 +178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
236
178
  exportAs: 'kendoGridUndoRedo',
237
179
  providers: [UndoRedoService]
238
180
  }]
239
- }], ctorParameters: function () { return [{ type: i1.GridComponent }, { type: i2.EditService }, { type: i3.UndoRedoService }, { type: i4.ChangeNotificationService }, { type: i5.ContextService }, { type: i6.LocalDataChangesService }]; }, propDecorators: { maxStoredStates: [{
240
- type: Input
241
- }], itemIdKey: [{
181
+ }], ctorParameters: function () { return [{ type: i1.GridComponent }, { type: i2.EditService }, { type: i3.UndoRedoService }, { type: i4.ChangeNotificationService }]; }, propDecorators: { maxStoredStates: [{
242
182
  type: Input
243
183
  }], onUndo: [{
244
184
  type: Output,
@@ -13,6 +13,7 @@ export class UndoRedoService {
13
13
  onUndo = new Subject();
14
14
  onRedo = new Subject();
15
15
  stackEndReached = new Subject();
16
+ setState = new Subject();
16
17
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17
18
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService });
18
19
  }
@@ -139,12 +139,6 @@ export class UndoRedoStack {
139
139
  this.currentNode = this.currentNode.previous;
140
140
  return this.currentNode.state;
141
141
  }
142
- peekNext() {
143
- return this.currentNode.next?.state || null;
144
- }
145
- peekPrev() {
146
- return this.currentNode.previous?.state || null;
147
- }
148
142
  /**
149
143
  * Performs a redo operation, moving to the next state
150
144
  * @returns The next state or null if can't redo