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

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.
@@ -532,6 +532,9 @@ const isMultipleRangesEnabled = (selectableSettings) => {
532
532
  */
533
533
  const calcRowHeight = (tableBody) => {
534
534
  let result = 0;
535
+ if (!isDocumentAvailable()) {
536
+ return result;
537
+ }
535
538
  if (tableBody) {
536
539
  const row = tableBody.insertRow(0);
537
540
  const cell = row.insertCell(0);
@@ -865,7 +868,7 @@ class ContextService {
865
868
  topToolbarNavigation;
866
869
  bottomToolbarNavigation;
867
870
  navigable;
868
- groupBindingDirective;
871
+ dataBindingDirective;
869
872
  constructor(renderer, localization) {
870
873
  this.renderer = renderer;
871
874
  this.localization = localization;
@@ -16672,7 +16675,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
16672
16675
  */
16673
16676
  class CellSelectionAggregateService {
16674
16677
  ctx;
16675
- dataChanges;
16676
16678
  columnInfoService;
16677
16679
  selectedItems = [];
16678
16680
  groupedAggregates = { dates: [], numbers: [], booleans: [] };
@@ -16688,9 +16690,8 @@ class CellSelectionAggregateService {
16688
16690
  latest: null
16689
16691
  };
16690
16692
  sub = new Subscription();
16691
- constructor(ctx, dataChanges, columnInfoService) {
16693
+ constructor(ctx, columnInfoService) {
16692
16694
  this.ctx = ctx;
16693
- this.dataChanges = dataChanges;
16694
16695
  this.columnInfoService = columnInfoService;
16695
16696
  }
16696
16697
  ngOnDestroy() {
@@ -16851,12 +16852,12 @@ class CellSelectionAggregateService {
16851
16852
  this.aggregates['isFalse'] = this.aggregates['isTrue'] = null;
16852
16853
  this.aggregates['earliest'] = this.aggregates['latest'] = null;
16853
16854
  }
16854
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, deps: [{ token: ContextService }, { token: LocalDataChangesService }, { token: ColumnInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
16855
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, deps: [{ token: ContextService }, { token: ColumnInfoService }], target: i0.ɵɵFactoryTarget.Injectable });
16855
16856
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService });
16856
16857
  }
16857
16858
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, decorators: [{
16858
16859
  type: Injectable
16859
- }], ctorParameters: function () { return [{ type: ContextService }, { type: LocalDataChangesService }, { type: ColumnInfoService }]; } });
16860
+ }], ctorParameters: function () { return [{ type: ContextService }, { type: ColumnInfoService }]; } });
16860
16861
 
16861
16862
  /**
16862
16863
  * @hidden
@@ -21213,8 +21214,8 @@ const packageMetadata = {
21213
21214
  productName: 'Kendo UI for Angular',
21214
21215
  productCode: 'KENDOUIANGULAR',
21215
21216
  productCodes: ['KENDOUIANGULAR'],
21216
- publishDate: 1750851099,
21217
- version: '19.2.0-develop.3',
21217
+ publishDate: 1750959047,
21218
+ version: '19.2.0-develop.5',
21218
21219
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
21219
21220
  };
21220
21221
 
@@ -23595,7 +23596,8 @@ class ListComponent {
23595
23596
  if (this.virtualColumns && (!this.viewportColumns || this.viewportWidthChange())) {
23596
23597
  this.updateViewportColumns();
23597
23598
  }
23598
- if (this.isVirtual && this.ctx.grid && !this.ctx.grid.pageSize) {
23599
+ const shouldCalculatePageSize = isDocumentAvailable() && this.isVirtual && this.ctx.grid && !this.ctx.grid.pageSize;
23600
+ if (shouldCalculatePageSize) {
23599
23601
  const calculatedPageSize = this.calcVirtualPageSize();
23600
23602
  if (calculatedPageSize > 0) {
23601
23603
  this.ngZone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {
@@ -27643,6 +27645,538 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
27643
27645
  args: [GroupToolbarToolComponent]
27644
27646
  }] } });
27645
27647
 
27648
+ /**
27649
+ * A directive that handles in-memory data operations like [paging]({% slug paging_grid %}),
27650
+ * [sorting]({% slug sorting_grid %}), and [grouping]({% slug grouping_grid %}).
27651
+ *
27652
+ * Use this directive with local data and enable the Grid data operations with minimal configuration.
27653
+ * ([More information and examples]({% slug local_data_grid %}#toc-using-the-data-binding-directive)).
27654
+ *
27655
+ * @example
27656
+ * ```html
27657
+ * <kendo-grid [kendoGridBinding]="gridData"></kendo-grid>
27658
+ * ```
27659
+ * @remarks
27660
+ * Applied to: {@link GridComponent}.
27661
+ */
27662
+ class DataBindingDirective {
27663
+ grid;
27664
+ changeDetector;
27665
+ localDataChangesService;
27666
+ rowReorderService;
27667
+ /**
27668
+ * Sets the number of records to skip in the Grid.
27669
+ *
27670
+ * @default 0
27671
+ */
27672
+ set skip(value) {
27673
+ if (!isPresent(value)) {
27674
+ value = 0;
27675
+ }
27676
+ this.grid.skip = this.state.skip = value;
27677
+ if (this.rowReorderService) {
27678
+ this.rowReorderService.skip = value;
27679
+ }
27680
+ }
27681
+ /**
27682
+ * Sets the sort descriptors for the Grid data.
27683
+ *
27684
+ */
27685
+ set sort(value) {
27686
+ this.grid.sort = this.state.sort = value;
27687
+ }
27688
+ /**
27689
+ * Sets the filter descriptor for the Grid data.
27690
+ *
27691
+ */
27692
+ set filter(value) {
27693
+ this.grid.filter = this.state.filter = value;
27694
+ }
27695
+ /**
27696
+ * Sets the page size for the Grid pager.
27697
+ *
27698
+ */
27699
+ set pageSize(value) {
27700
+ this.grid.pageSize = this.state.take = value;
27701
+ }
27702
+ /**
27703
+ * Sets the group descriptors for the Grid data.
27704
+ *
27705
+ */
27706
+ set group(value) {
27707
+ this.grid.group = this.state.group = value;
27708
+ }
27709
+ /**
27710
+ * Sets the data array for the Grid.
27711
+ *
27712
+ */
27713
+ set data(value) {
27714
+ this.originalData = value || [];
27715
+ if (this.localDataChangesService) {
27716
+ this.localDataChangesService.data = value;
27717
+ }
27718
+ this.dataChanged = true;
27719
+ }
27720
+ state = {
27721
+ skip: 0
27722
+ };
27723
+ originalData = [];
27724
+ dataChanged;
27725
+ stateChangeSubscription;
27726
+ dataChangedSubscription;
27727
+ rowReorderSubscription;
27728
+ constructor(grid, changeDetector, localDataChangesService, rowReorderService, ctx) {
27729
+ this.grid = grid;
27730
+ this.changeDetector = changeDetector;
27731
+ this.localDataChangesService = localDataChangesService;
27732
+ this.rowReorderService = rowReorderService;
27733
+ if (localDataChangesService) {
27734
+ this.dataChangedSubscription = this.localDataChangesService.changes.subscribe(this.rebind.bind(this));
27735
+ }
27736
+ ctx && (ctx.dataBindingDirective = this);
27737
+ }
27738
+ /**
27739
+ * @hidden
27740
+ */
27741
+ ngOnInit() {
27742
+ this.applyState(this.state);
27743
+ this.stateChangeSubscription = this.grid
27744
+ .dataStateChange
27745
+ .subscribe(this.onStateChange.bind(this));
27746
+ if (this.rowReorderService) {
27747
+ this.rowReorderSubscription = this.grid
27748
+ .rowReorder
27749
+ .subscribe(this.onRowReorder.bind(this));
27750
+ }
27751
+ }
27752
+ /**
27753
+ * @hidden
27754
+ */
27755
+ ngOnDestroy() {
27756
+ if (this.stateChangeSubscription) {
27757
+ this.stateChangeSubscription.unsubscribe();
27758
+ }
27759
+ if (this.dataChangedSubscription) {
27760
+ this.dataChangedSubscription.unsubscribe();
27761
+ }
27762
+ if (this.rowReorderSubscription) {
27763
+ this.rowReorderSubscription.unsubscribe();
27764
+ }
27765
+ }
27766
+ /**
27767
+ * @hidden
27768
+ */
27769
+ ngOnChanges(changes) {
27770
+ if (anyChanged(["pageSize", "skip", "sort", "group", "filter"], changes)) {
27771
+ this.rebind();
27772
+ }
27773
+ }
27774
+ ngDoCheck() {
27775
+ if (this.dataChanged) {
27776
+ this.updateGridData();
27777
+ }
27778
+ }
27779
+ /**
27780
+ * @hidden
27781
+ */
27782
+ onStateChange(state) {
27783
+ this.applyState(state);
27784
+ this.rebind();
27785
+ }
27786
+ /**
27787
+ * @hidden
27788
+ */
27789
+ onRowReorder(ev) {
27790
+ this.rowReorderService.reorderRows(ev, this.originalData);
27791
+ this.rebind();
27792
+ }
27793
+ /**
27794
+ * @hidden
27795
+ */
27796
+ rebind() {
27797
+ this.data = this.originalData;
27798
+ this.updateGridData();
27799
+ this.notifyDataChange();
27800
+ }
27801
+ /**
27802
+ * Notifies the Grid that its data has changed.
27803
+ */
27804
+ notifyDataChange() {
27805
+ this.grid.onDataChange();
27806
+ if (this.changeDetector) {
27807
+ this.changeDetector.markForCheck();
27808
+ }
27809
+ }
27810
+ process(state) {
27811
+ if (this.grid.isVirtual && (!isPresent(state.take) || state.take === 0)) {
27812
+ return {
27813
+ data: [],
27814
+ total: this.originalData?.length || 0
27815
+ };
27816
+ }
27817
+ return process(this.originalData, state);
27818
+ }
27819
+ applyState({ skip, take, sort, group, filter }) {
27820
+ this.skip = skip;
27821
+ this.pageSize = take;
27822
+ this.sort = sort;
27823
+ this.group = group;
27824
+ this.filter = filter;
27825
+ }
27826
+ updateGridData() {
27827
+ this.grid.data = this.process(this.state);
27828
+ this.grid.updateNavigationMetadata();
27829
+ this.dataChanged = false;
27830
+ }
27831
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, deps: [{ token: GridComponent }, { token: i0.ChangeDetectorRef }, { token: LocalDataChangesService }, { token: RowReorderService }, { token: ContextService }], target: i0.ɵɵFactoryTarget.Directive });
27832
+ 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 });
27833
+ }
27834
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, decorators: [{
27835
+ type: Directive,
27836
+ args: [{
27837
+ selector: '[kendoGridBinding]',
27838
+ exportAs: 'kendoGridBinding',
27839
+ standalone: true
27840
+ }]
27841
+ }], ctorParameters: function () { return [{ type: GridComponent }, { type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: RowReorderService }, { type: ContextService }]; }, propDecorators: { skip: [{
27842
+ type: Input
27843
+ }], sort: [{
27844
+ type: Input
27845
+ }], filter: [{
27846
+ type: Input
27847
+ }], pageSize: [{
27848
+ type: Input
27849
+ }], group: [{
27850
+ type: Input
27851
+ }], data: [{
27852
+ type: Input,
27853
+ args: ["kendoGridBinding"]
27854
+ }] } });
27855
+
27856
+ const hasGroups = (items) => items && items.length && items[0].field && items[0].items;
27857
+ const groupDescriptorsPresent = (descriptors) => isPresent(descriptors) && descriptors.length > 0;
27858
+ const processGroups = (data, state) => process(data, state).data;
27859
+ const removeParentDescriptors = (parents, owner) => g => g.field !== owner.field && !parents.some(y => y.field === g.field);
27860
+ const findGroup = (groupIndex, groups) => {
27861
+ const parents = [];
27862
+ return {
27863
+ group: groupIndex.split("_").reduce((acc, x) => {
27864
+ const idx = parseInt(x, 10);
27865
+ if (acc.items) {
27866
+ parents.push(acc);
27867
+ return acc.items[idx];
27868
+ }
27869
+ return isArray(acc) ? acc[idx] : acc;
27870
+ }, groups),
27871
+ parents
27872
+ };
27873
+ };
27874
+ const findChildren = (data, parents) => {
27875
+ const filters = parents.map(p => ({ field: p.field, operator: "eq", value: p.value }));
27876
+ return filterBy(data, {
27877
+ filters: filters,
27878
+ logic: "and"
27879
+ });
27880
+ };
27881
+ /**
27882
+ * @hidden
27883
+ */
27884
+ const count = (groups, includeFooters = false) => (groups.reduce((acc, group) => {
27885
+ if (!group.skipHeader) {
27886
+ acc++;
27887
+ }
27888
+ if (group.items) {
27889
+ const children = count(group.items, includeFooters);
27890
+ if (includeFooters && children && !group.hideFooter) {
27891
+ acc++;
27892
+ }
27893
+ acc += children;
27894
+ }
27895
+ return acc;
27896
+ }, 0));
27897
+ /**
27898
+ * @hidden
27899
+ */
27900
+ const noDescriptors = (descriptors) => !isPresent(descriptors) || !descriptors.length;
27901
+ /**
27902
+ * @hidden
27903
+ */
27904
+ const slice = (groups, skip, take, includeFooters = false) => {
27905
+ if (!isPresent(take)) {
27906
+ return groups;
27907
+ }
27908
+ const result = [];
27909
+ for (let idx = 0, length = groups.length; idx < length; idx++) {
27910
+ if (take <= 0) {
27911
+ break;
27912
+ }
27913
+ const group = groups[idx];
27914
+ const groupItems = group.items;
27915
+ let itemCount = count(groupItems, includeFooters);
27916
+ if (includeFooters && groupItems.length) {
27917
+ itemCount++;
27918
+ }
27919
+ const skipHeader = skip > 0;
27920
+ if (skip) {
27921
+ skip--;
27922
+ if (itemCount && skip >= itemCount) {
27923
+ skip -= itemCount;
27924
+ continue;
27925
+ }
27926
+ }
27927
+ if (!skipHeader || itemCount) {
27928
+ const items = [];
27929
+ let hideFooter = true;
27930
+ if (!skipHeader) {
27931
+ take--;
27932
+ }
27933
+ if (take) {
27934
+ if (hasGroups(groupItems)) {
27935
+ const children = slice(groupItems, skip, take, includeFooters);
27936
+ items.push(...children);
27937
+ take -= count(children, includeFooters);
27938
+ }
27939
+ else {
27940
+ items.push(...groupItems.slice(skip, Math.min(skip + take, groupItems.length)));
27941
+ take -= items.length;
27942
+ }
27943
+ if (take && includeFooters) {
27944
+ hideFooter = false;
27945
+ take--;
27946
+ }
27947
+ skip = 0;
27948
+ }
27949
+ result.push({
27950
+ aggregates: group.aggregates,
27951
+ field: group.field,
27952
+ hideFooter,
27953
+ items,
27954
+ offset: idx,
27955
+ skipHeader,
27956
+ value: group.value
27957
+ });
27958
+ }
27959
+ }
27960
+ return result;
27961
+ };
27962
+ const skippedHeaders = (groupItem) => {
27963
+ let total = 0;
27964
+ while (groupItem) {
27965
+ if (groupItem.skipHeader) {
27966
+ total++;
27967
+ }
27968
+ groupItem = groupItem.items && groupItem.items[0] || null;
27969
+ }
27970
+ return total;
27971
+ };
27972
+ /**
27973
+ * A directive which encapsulates the in-memory handling of grouping with virtual scrolling.
27974
+ * @remarks
27975
+ * Applied to: {@link GridComponent}.
27976
+ */
27977
+ class GroupBindingDirective extends DataBindingDirective {
27978
+ groupsService;
27979
+ /**
27980
+ * The array of data which will be used to populate the Grid.
27981
+ */
27982
+ set kendoGridGroupBinding(value) {
27983
+ this.groups = null;
27984
+ this.grid.resetGroupsState();
27985
+ this.data = value;
27986
+ }
27987
+ /**
27988
+ * @hidden
27989
+ */
27990
+ set data(value) {
27991
+ this.originalData = value || [];
27992
+ this.dataChanged = true;
27993
+ }
27994
+ /**
27995
+ * Defines the descriptors by which the data will be sorted.
27996
+ */
27997
+ set sort(value) {
27998
+ const noCurrentDescriptors = noDescriptors(this.state.sort);
27999
+ const noIncomingDescriptors = noDescriptors(value);
28000
+ const clear = this.state.sort !== value && !(noCurrentDescriptors && noIncomingDescriptors);
28001
+ this.grid.sort = this.state.sort = value;
28002
+ if (clear) {
28003
+ this.groups = null;
28004
+ this.grid.resetGroupsState();
28005
+ }
28006
+ }
28007
+ /**
28008
+ * Defines the descriptor by which the data will be filtered.
28009
+ */
28010
+ set filter(value) {
28011
+ const clear = diffFilters(this.state.filter, value);
28012
+ if (clear) {
28013
+ this.state.filter = value;
28014
+ this.grid.filter = cloneFilters(value);
28015
+ this.groups = null;
28016
+ this.grid.resetGroupsState();
28017
+ }
28018
+ }
28019
+ /**
28020
+ * Defines the descriptors by which the data will be grouped.
28021
+ */
28022
+ set group(value) {
28023
+ // don't clear if no groups are present in previous and current value
28024
+ const groupsPresent = groupDescriptorsPresent(this.state.group) || groupDescriptorsPresent(value);
28025
+ const clear = this.state.group !== value && groupsPresent;
28026
+ this.grid.group = this.state.group = value;
28027
+ if (clear) {
28028
+ this.groups = null;
28029
+ this.grid.resetGroupsState();
28030
+ this.skip = 0;
28031
+ }
28032
+ }
28033
+ groups;
28034
+ gridSubs = new Subscription();
28035
+ constructor(changeDetector, localDataChangesService, ctxService, groupsService) {
28036
+ super(ctxService.grid, changeDetector, localDataChangesService, null, ctxService);
28037
+ this.groupsService = groupsService;
28038
+ ctxService.dataBindingDirective = this;
28039
+ }
28040
+ ngOnInit() {
28041
+ super.ngOnInit();
28042
+ this.gridSubs.add(this.grid.groupExpand.subscribe(this.groupExpand.bind(this)));
28043
+ this.gridSubs.add(this.grid.groupCollapse.subscribe(this.groupCollapse.bind(this)));
28044
+ }
28045
+ ngAfterContentInit() {
28046
+ if (isDevMode() && this.grid.isGroupExpanded) {
28047
+ throw new Error(GridConfigurationErrorMessages.groupBindingDirectives);
28048
+ }
28049
+ }
28050
+ ngOnDestroy() {
28051
+ this.gridSubs.unsubscribe();
28052
+ }
28053
+ /**
28054
+ * @hidden
28055
+ */
28056
+ toggleAll(expand) {
28057
+ this.skip = 0;
28058
+ this.grid.scrollTo({ row: 0, column: 0 });
28059
+ this.groups.forEach((gr, idx) => {
28060
+ const expanded = this.groupsService.isExpanded({
28061
+ group: gr,
28062
+ groupIndex: idx.toString(),
28063
+ parentGroup: undefined
28064
+ });
28065
+ const performToggle = (expand && !expanded) || (!expand && expanded);
28066
+ if (performToggle) {
28067
+ this.grid.groupsService.toggleRow({
28068
+ type: 'group',
28069
+ data: gr,
28070
+ index: idx.toString(),
28071
+ level: 0,
28072
+ parentGroup: undefined
28073
+ });
28074
+ this[expand ? 'groupExpand' : 'groupCollapse']({ groupIndex: idx.toString() });
28075
+ }
28076
+ });
28077
+ }
28078
+ /**
28079
+ * Collapses all expanded root level groups.
28080
+ */
28081
+ collapseAll() {
28082
+ this.toggleAll(false);
28083
+ }
28084
+ /**
28085
+ * Expands all expanded root level groups.
28086
+ */
28087
+ expandAll() {
28088
+ this.toggleAll(true);
28089
+ }
28090
+ /**
28091
+ * @hidden
28092
+ */
28093
+ groupExpand({ groupIndex }) {
28094
+ const { group, parents } = findGroup(groupIndex, this.groups);
28095
+ if (!group) {
28096
+ return;
28097
+ }
28098
+ this.groupsService.expandChildren(groupIndex);
28099
+ if (!group.items.length) {
28100
+ const descriptors = this.state.group.filter(removeParentDescriptors(parents, group));
28101
+ const children = findChildren(this.originalData, parents.concat(group));
28102
+ group.items = processGroups(children, {
28103
+ filter: this.state.filter,
28104
+ group: descriptors,
28105
+ sort: this.state.sort
28106
+ });
28107
+ }
28108
+ this.grid.data = this.dataResult(this.state.skip, this.state.take);
28109
+ }
28110
+ /**
28111
+ * @hidden
28112
+ */
28113
+ groupCollapse({ groupIndex }) {
28114
+ const { group } = findGroup(groupIndex, this.groups);
28115
+ if (group) {
28116
+ group.items = [];
28117
+ }
28118
+ else {
28119
+ return;
28120
+ }
28121
+ this.grid.data = this.dataResult(this.state.skip, this.state.take);
28122
+ }
28123
+ process(state) {
28124
+ if (state.group && state.group.length) {
28125
+ const groups = this.processGroups(state);
28126
+ this.grid.skip -= skippedHeaders(groups.data[0]);
28127
+ return groups;
28128
+ }
28129
+ else {
28130
+ this.groups = null;
28131
+ }
28132
+ return super.process(state);
28133
+ }
28134
+ processGroups(state) {
28135
+ if (!this.groups || !this.groups.length) {
28136
+ this.groups = processGroups(this.originalData, {
28137
+ filter: state.filter,
28138
+ group: state.group,
28139
+ sort: state.sort
28140
+ });
28141
+ }
28142
+ return this.dataResult(state.skip, state.take);
28143
+ }
28144
+ dataResult(skip, take) {
28145
+ const includeFooters = this.grid.showGroupFooters;
28146
+ return {
28147
+ data: slice(this.groups, skip, take, includeFooters),
28148
+ total: count(this.groups, includeFooters)
28149
+ };
28150
+ }
28151
+ applyState({ skip, take, sort, group, filter }) {
28152
+ this.skip = skip;
28153
+ this.state.take = take;
28154
+ // this.pageSize = take; // do need to update take as the process with slice correctly
28155
+ this.sort = sort;
28156
+ this.group = group;
28157
+ this.filter = filter;
28158
+ }
28159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupBindingDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: LocalDataChangesService }, { token: ContextService }, { token: GroupsService }], target: i0.ɵɵFactoryTarget.Directive });
28160
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GroupBindingDirective, isStandalone: true, selector: "[kendoGridGroupBinding]", inputs: { kendoGridGroupBinding: "kendoGridGroupBinding", sort: "sort", filter: "filter", group: "group" }, exportAs: ["kendoGridGroupBinding"], usesInheritance: true, ngImport: i0 });
28161
+ }
28162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupBindingDirective, decorators: [{
28163
+ type: Directive,
28164
+ args: [{
28165
+ selector: '[kendoGridGroupBinding]',
28166
+ exportAs: 'kendoGridGroupBinding',
28167
+ standalone: true
28168
+ }]
28169
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: ContextService }, { type: GroupsService }]; }, propDecorators: { kendoGridGroupBinding: [{
28170
+ type: Input,
28171
+ args: ["kendoGridGroupBinding"]
28172
+ }], sort: [{
28173
+ type: Input
28174
+ }], filter: [{
28175
+ type: Input
28176
+ }], group: [{
28177
+ type: Input
28178
+ }] } });
28179
+
27646
28180
  const createControl = (source) => (acc, key) => {
27647
28181
  acc[key] = new FormControl(source[key]);
27648
28182
  return acc;
@@ -29123,12 +29657,12 @@ class GridComponent {
29123
29657
  this.sort = state.sort;
29124
29658
  this.group = state.group;
29125
29659
  this.filter = state.filter;
29126
- this.group = state.group;
29127
29660
  this.skip = state.skip;
29128
29661
  this.pageSize = state.take;
29129
- this.data = state.currentData;
29130
- this.changeNotification.notify();
29131
- this.changeDetectorRef.detectChanges();
29662
+ if (state.currentData) {
29663
+ this.data = state.currentData;
29664
+ }
29665
+ this.changeDetectorRef.markForCheck();
29132
29666
  }
29133
29667
  traverseColumns(columns, callback) {
29134
29668
  columns.forEach((column) => {
@@ -29817,8 +30351,8 @@ class GridComponent {
29817
30351
  }
29818
30352
  if (this.groupsService.isExpanded({ groupIndex: index }) !== expand) {
29819
30353
  this.groupsService.toggleRow({ index }, false);
29820
- if (this.ctx.groupBindingDirective) {
29821
- this.ctx.groupBindingDirective[`group${expand ? 'Expand' : 'Collapse'}`]({ groupIndex: index });
30354
+ if (this.ctx.dataBindingDirective && this.ctx.dataBindingDirective instanceof GroupBindingDirective) {
30355
+ this.ctx.dataBindingDirective[`group${expand ? 'Expand' : 'Collapse'}`]({ groupIndex: index });
29822
30356
  }
29823
30357
  }
29824
30358
  }
@@ -31756,213 +32290,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
31756
32290
  }]
31757
32291
  }], ctorParameters: function () { return [{ type: i1$2.LocalizationService }]; } });
31758
32292
 
31759
- /**
31760
- * A directive that handles in-memory data operations like [paging]({% slug paging_grid %}),
31761
- * [sorting]({% slug sorting_grid %}), and [grouping]({% slug grouping_grid %}).
31762
- *
31763
- * Use this directive with local data and enable the Grid data operations with minimal configuration.
31764
- * ([More information and examples]({% slug local_data_grid %}#toc-using-the-data-binding-directive)).
31765
- *
31766
- * @example
31767
- * ```html
31768
- * <kendo-grid [kendoGridBinding]="gridData"></kendo-grid>
31769
- * ```
31770
- * @remarks
31771
- * Applied to: {@link GridComponent}.
31772
- */
31773
- class DataBindingDirective {
31774
- grid;
31775
- changeDetector;
31776
- localDataChangesService;
31777
- rowReorderService;
31778
- /**
31779
- * Sets the number of records to skip in the Grid.
31780
- *
31781
- * @default 0
31782
- */
31783
- set skip(value) {
31784
- if (!isPresent(value)) {
31785
- value = 0;
31786
- }
31787
- this.grid.skip = this.state.skip = value;
31788
- if (this.rowReorderService) {
31789
- this.rowReorderService.skip = value;
31790
- }
31791
- }
31792
- /**
31793
- * Sets the sort descriptors for the Grid data.
31794
- *
31795
- */
31796
- set sort(value) {
31797
- this.grid.sort = this.state.sort = value;
31798
- }
31799
- /**
31800
- * Sets the filter descriptor for the Grid data.
31801
- *
31802
- */
31803
- set filter(value) {
31804
- this.grid.filter = this.state.filter = value;
31805
- }
31806
- /**
31807
- * Sets the page size for the Grid pager.
31808
- *
31809
- */
31810
- set pageSize(value) {
31811
- this.grid.pageSize = this.state.take = value;
31812
- }
31813
- /**
31814
- * Sets the group descriptors for the Grid data.
31815
- *
31816
- */
31817
- set group(value) {
31818
- this.grid.group = this.state.group = value;
31819
- }
31820
- /**
31821
- * Sets the data array for the Grid.
31822
- *
31823
- */
31824
- set data(value) {
31825
- this.originalData = value || [];
31826
- if (this.localDataChangesService) {
31827
- this.localDataChangesService.data = value;
31828
- }
31829
- this.dataChanged = true;
31830
- }
31831
- state = {
31832
- skip: 0
31833
- };
31834
- originalData = [];
31835
- dataChanged;
31836
- stateChangeSubscription;
31837
- dataChangedSubscription;
31838
- rowReorderSubscription;
31839
- constructor(grid, changeDetector, localDataChangesService, rowReorderService) {
31840
- this.grid = grid;
31841
- this.changeDetector = changeDetector;
31842
- this.localDataChangesService = localDataChangesService;
31843
- this.rowReorderService = rowReorderService;
31844
- if (localDataChangesService) {
31845
- this.dataChangedSubscription = this.localDataChangesService.changes.subscribe(this.rebind.bind(this));
31846
- }
31847
- }
31848
- /**
31849
- * @hidden
31850
- */
31851
- ngOnInit() {
31852
- this.applyState(this.state);
31853
- this.stateChangeSubscription = this.grid
31854
- .dataStateChange
31855
- .subscribe(this.onStateChange.bind(this));
31856
- if (this.rowReorderService) {
31857
- this.rowReorderSubscription = this.grid
31858
- .rowReorder
31859
- .subscribe(this.onRowReorder.bind(this));
31860
- }
31861
- }
31862
- /**
31863
- * @hidden
31864
- */
31865
- ngOnDestroy() {
31866
- if (this.stateChangeSubscription) {
31867
- this.stateChangeSubscription.unsubscribe();
31868
- }
31869
- if (this.dataChangedSubscription) {
31870
- this.dataChangedSubscription.unsubscribe();
31871
- }
31872
- if (this.rowReorderSubscription) {
31873
- this.rowReorderSubscription.unsubscribe();
31874
- }
31875
- }
31876
- /**
31877
- * @hidden
31878
- */
31879
- ngOnChanges(changes) {
31880
- if (anyChanged(["pageSize", "skip", "sort", "group", "filter"], changes)) {
31881
- this.rebind();
31882
- }
31883
- }
31884
- ngDoCheck() {
31885
- if (this.dataChanged) {
31886
- this.updateGridData();
31887
- }
31888
- }
31889
- /**
31890
- * @hidden
31891
- */
31892
- onStateChange(state) {
31893
- this.applyState(state);
31894
- this.rebind();
31895
- }
31896
- /**
31897
- * @hidden
31898
- */
31899
- onRowReorder(ev) {
31900
- this.rowReorderService.reorderRows(ev, this.originalData);
31901
- this.rebind();
31902
- }
31903
- /**
31904
- * @hidden
31905
- */
31906
- rebind() {
31907
- this.data = this.originalData;
31908
- this.updateGridData();
31909
- this.notifyDataChange();
31910
- }
31911
- /**
31912
- * Notifies the Grid that its data has changed.
31913
- */
31914
- notifyDataChange() {
31915
- this.grid.onDataChange();
31916
- if (this.changeDetector) {
31917
- this.changeDetector.markForCheck();
31918
- }
31919
- }
31920
- process(state) {
31921
- if (this.grid.isVirtual && (!isPresent(state.take) || state.take === 0)) {
31922
- return {
31923
- data: [],
31924
- total: this.originalData?.length || 0
31925
- };
31926
- }
31927
- return process(this.originalData, state);
31928
- }
31929
- applyState({ skip, take, sort, group, filter }) {
31930
- this.skip = skip;
31931
- this.pageSize = take;
31932
- this.sort = sort;
31933
- this.group = group;
31934
- this.filter = filter;
31935
- }
31936
- updateGridData() {
31937
- this.grid.data = this.process(this.state);
31938
- this.grid.updateNavigationMetadata();
31939
- this.dataChanged = false;
31940
- }
31941
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, deps: [{ token: GridComponent }, { token: i0.ChangeDetectorRef }, { token: LocalDataChangesService }, { token: RowReorderService }], target: i0.ɵɵFactoryTarget.Directive });
31942
- 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 });
31943
- }
31944
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, decorators: [{
31945
- type: Directive,
31946
- args: [{
31947
- selector: '[kendoGridBinding]',
31948
- exportAs: 'kendoGridBinding',
31949
- standalone: true
31950
- }]
31951
- }], ctorParameters: function () { return [{ type: GridComponent }, { type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: RowReorderService }]; }, propDecorators: { skip: [{
31952
- type: Input
31953
- }], sort: [{
31954
- type: Input
31955
- }], filter: [{
31956
- type: Input
31957
- }], pageSize: [{
31958
- type: Input
31959
- }], group: [{
31960
- type: Input
31961
- }], data: [{
31962
- type: Input,
31963
- args: ["kendoGridBinding"]
31964
- }] } });
31965
-
31966
32293
  /**
31967
32294
  * Stores the row selection state of the Grid in memory
31968
32295
  * ([see example]({% slug selection_grid %}#toc-toggling-the-selection-functionality)).
@@ -32865,330 +33192,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
32865
33192
  type: Input
32866
33193
  }] } });
32867
33194
 
32868
- const hasGroups = (items) => items && items.length && items[0].field && items[0].items;
32869
- const groupDescriptorsPresent = (descriptors) => isPresent(descriptors) && descriptors.length > 0;
32870
- const processGroups = (data, state) => process(data, state).data;
32871
- const removeParentDescriptors = (parents, owner) => g => g.field !== owner.field && !parents.some(y => y.field === g.field);
32872
- const findGroup = (groupIndex, groups) => {
32873
- const parents = [];
32874
- return {
32875
- group: groupIndex.split("_").reduce((acc, x) => {
32876
- const idx = parseInt(x, 10);
32877
- if (acc.items) {
32878
- parents.push(acc);
32879
- return acc.items[idx];
32880
- }
32881
- return isArray(acc) ? acc[idx] : acc;
32882
- }, groups),
32883
- parents
32884
- };
32885
- };
32886
- const findChildren = (data, parents) => {
32887
- const filters = parents.map(p => ({ field: p.field, operator: "eq", value: p.value }));
32888
- return filterBy(data, {
32889
- filters: filters,
32890
- logic: "and"
32891
- });
32892
- };
32893
- /**
32894
- * @hidden
32895
- */
32896
- const count = (groups, includeFooters = false) => (groups.reduce((acc, group) => {
32897
- if (!group.skipHeader) {
32898
- acc++;
32899
- }
32900
- if (group.items) {
32901
- const children = count(group.items, includeFooters);
32902
- if (includeFooters && children && !group.hideFooter) {
32903
- acc++;
32904
- }
32905
- acc += children;
32906
- }
32907
- return acc;
32908
- }, 0));
32909
- /**
32910
- * @hidden
32911
- */
32912
- const noDescriptors = (descriptors) => !isPresent(descriptors) || !descriptors.length;
32913
- /**
32914
- * @hidden
32915
- */
32916
- const slice = (groups, skip, take, includeFooters = false) => {
32917
- if (!isPresent(take)) {
32918
- return groups;
32919
- }
32920
- const result = [];
32921
- for (let idx = 0, length = groups.length; idx < length; idx++) {
32922
- if (take <= 0) {
32923
- break;
32924
- }
32925
- const group = groups[idx];
32926
- const groupItems = group.items;
32927
- let itemCount = count(groupItems, includeFooters);
32928
- if (includeFooters && groupItems.length) {
32929
- itemCount++;
32930
- }
32931
- const skipHeader = skip > 0;
32932
- if (skip) {
32933
- skip--;
32934
- if (itemCount && skip >= itemCount) {
32935
- skip -= itemCount;
32936
- continue;
32937
- }
32938
- }
32939
- if (!skipHeader || itemCount) {
32940
- const items = [];
32941
- let hideFooter = true;
32942
- if (!skipHeader) {
32943
- take--;
32944
- }
32945
- if (take) {
32946
- if (hasGroups(groupItems)) {
32947
- const children = slice(groupItems, skip, take, includeFooters);
32948
- items.push(...children);
32949
- take -= count(children, includeFooters);
32950
- }
32951
- else {
32952
- items.push(...groupItems.slice(skip, Math.min(skip + take, groupItems.length)));
32953
- take -= items.length;
32954
- }
32955
- if (take && includeFooters) {
32956
- hideFooter = false;
32957
- take--;
32958
- }
32959
- skip = 0;
32960
- }
32961
- result.push({
32962
- aggregates: group.aggregates,
32963
- field: group.field,
32964
- hideFooter,
32965
- items,
32966
- offset: idx,
32967
- skipHeader,
32968
- value: group.value
32969
- });
32970
- }
32971
- }
32972
- return result;
32973
- };
32974
- const skippedHeaders = (groupItem) => {
32975
- let total = 0;
32976
- while (groupItem) {
32977
- if (groupItem.skipHeader) {
32978
- total++;
32979
- }
32980
- groupItem = groupItem.items && groupItem.items[0] || null;
32981
- }
32982
- return total;
32983
- };
32984
- /**
32985
- * A directive which encapsulates the in-memory handling of grouping with virtual scrolling.
32986
- * @remarks
32987
- * Applied to: {@link GridComponent}.
32988
- */
32989
- class GroupBindingDirective extends DataBindingDirective {
32990
- groupsService;
32991
- /**
32992
- * The array of data which will be used to populate the Grid.
32993
- */
32994
- set kendoGridGroupBinding(value) {
32995
- this.groups = null;
32996
- this.grid.resetGroupsState();
32997
- this.data = value;
32998
- }
32999
- /**
33000
- * @hidden
33001
- */
33002
- set data(value) {
33003
- this.originalData = value || [];
33004
- this.dataChanged = true;
33005
- }
33006
- /**
33007
- * Defines the descriptors by which the data will be sorted.
33008
- */
33009
- set sort(value) {
33010
- const noCurrentDescriptors = noDescriptors(this.state.sort);
33011
- const noIncomingDescriptors = noDescriptors(value);
33012
- const clear = this.state.sort !== value && !(noCurrentDescriptors && noIncomingDescriptors);
33013
- this.grid.sort = this.state.sort = value;
33014
- if (clear) {
33015
- this.groups = null;
33016
- this.grid.resetGroupsState();
33017
- }
33018
- }
33019
- /**
33020
- * Defines the descriptor by which the data will be filtered.
33021
- */
33022
- set filter(value) {
33023
- const clear = diffFilters(this.state.filter, value);
33024
- if (clear) {
33025
- this.state.filter = value;
33026
- this.grid.filter = cloneFilters(value);
33027
- this.groups = null;
33028
- this.grid.resetGroupsState();
33029
- }
33030
- }
33031
- /**
33032
- * Defines the descriptors by which the data will be grouped.
33033
- */
33034
- set group(value) {
33035
- // don't clear if no groups are present in previous and current value
33036
- const groupsPresent = groupDescriptorsPresent(this.state.group) || groupDescriptorsPresent(value);
33037
- const clear = this.state.group !== value && groupsPresent;
33038
- this.grid.group = this.state.group = value;
33039
- if (clear) {
33040
- this.groups = null;
33041
- this.grid.resetGroupsState();
33042
- this.skip = 0;
33043
- }
33044
- }
33045
- groups;
33046
- gridSubs = new Subscription();
33047
- constructor(changeDetector, localDataChangesService, ctxService, groupsService) {
33048
- super(ctxService.grid, changeDetector, localDataChangesService);
33049
- this.groupsService = groupsService;
33050
- ctxService.groupBindingDirective = this;
33051
- }
33052
- ngOnInit() {
33053
- super.ngOnInit();
33054
- this.gridSubs.add(this.grid.groupExpand.subscribe(this.groupExpand.bind(this)));
33055
- this.gridSubs.add(this.grid.groupCollapse.subscribe(this.groupCollapse.bind(this)));
33056
- }
33057
- ngAfterContentInit() {
33058
- if (isDevMode() && this.grid.isGroupExpanded) {
33059
- throw new Error(GridConfigurationErrorMessages.groupBindingDirectives);
33060
- }
33061
- }
33062
- ngOnDestroy() {
33063
- this.gridSubs.unsubscribe();
33064
- }
33065
- /**
33066
- * @hidden
33067
- */
33068
- toggleAll(expand) {
33069
- this.skip = 0;
33070
- this.grid.scrollTo({ row: 0, column: 0 });
33071
- this.groups.forEach((gr, idx) => {
33072
- const expanded = this.groupsService.isExpanded({
33073
- group: gr,
33074
- groupIndex: idx.toString(),
33075
- parentGroup: undefined
33076
- });
33077
- const performToggle = (expand && !expanded) || (!expand && expanded);
33078
- if (performToggle) {
33079
- this.grid.groupsService.toggleRow({
33080
- type: 'group',
33081
- data: gr,
33082
- index: idx.toString(),
33083
- level: 0,
33084
- parentGroup: undefined
33085
- });
33086
- this[expand ? 'groupExpand' : 'groupCollapse']({ groupIndex: idx.toString() });
33087
- }
33088
- });
33089
- }
33090
- /**
33091
- * Collapses all expanded root level groups.
33092
- */
33093
- collapseAll() {
33094
- this.toggleAll(false);
33095
- }
33096
- /**
33097
- * Expands all expanded root level groups.
33098
- */
33099
- expandAll() {
33100
- this.toggleAll(true);
33101
- }
33102
- /**
33103
- * @hidden
33104
- */
33105
- groupExpand({ groupIndex }) {
33106
- const { group, parents } = findGroup(groupIndex, this.groups);
33107
- if (!group) {
33108
- return;
33109
- }
33110
- this.groupsService.expandChildren(groupIndex);
33111
- if (!group.items.length) {
33112
- const descriptors = this.state.group.filter(removeParentDescriptors(parents, group));
33113
- const children = findChildren(this.originalData, parents.concat(group));
33114
- group.items = processGroups(children, {
33115
- filter: this.state.filter,
33116
- group: descriptors,
33117
- sort: this.state.sort
33118
- });
33119
- }
33120
- this.grid.data = this.dataResult(this.state.skip, this.state.take);
33121
- }
33122
- /**
33123
- * @hidden
33124
- */
33125
- groupCollapse({ groupIndex }) {
33126
- const { group } = findGroup(groupIndex, this.groups);
33127
- if (group) {
33128
- group.items = [];
33129
- }
33130
- else {
33131
- return;
33132
- }
33133
- this.grid.data = this.dataResult(this.state.skip, this.state.take);
33134
- }
33135
- process(state) {
33136
- if (state.group && state.group.length) {
33137
- const groups = this.processGroups(state);
33138
- this.grid.skip -= skippedHeaders(groups.data[0]);
33139
- return groups;
33140
- }
33141
- else {
33142
- this.groups = null;
33143
- }
33144
- return super.process(state);
33145
- }
33146
- processGroups(state) {
33147
- if (!this.groups || !this.groups.length) {
33148
- this.groups = processGroups(this.originalData, {
33149
- filter: state.filter,
33150
- group: state.group,
33151
- sort: state.sort
33152
- });
33153
- }
33154
- return this.dataResult(state.skip, state.take);
33155
- }
33156
- dataResult(skip, take) {
33157
- const includeFooters = this.grid.showGroupFooters;
33158
- return {
33159
- data: slice(this.groups, skip, take, includeFooters),
33160
- total: count(this.groups, includeFooters)
33161
- };
33162
- }
33163
- applyState({ skip, take, sort, group, filter }) {
33164
- this.skip = skip;
33165
- this.state.take = take;
33166
- // this.pageSize = take; // do need to update take as the process with slice correctly
33167
- this.sort = sort;
33168
- this.group = group;
33169
- this.filter = filter;
33170
- }
33171
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupBindingDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: LocalDataChangesService }, { token: ContextService }, { token: GroupsService }], target: i0.ɵɵFactoryTarget.Directive });
33172
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: GroupBindingDirective, isStandalone: true, selector: "[kendoGridGroupBinding]", inputs: { kendoGridGroupBinding: "kendoGridGroupBinding", sort: "sort", filter: "filter", group: "group" }, exportAs: ["kendoGridGroupBinding"], usesInheritance: true, ngImport: i0 });
33173
- }
33174
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupBindingDirective, decorators: [{
33175
- type: Directive,
33176
- args: [{
33177
- selector: '[kendoGridGroupBinding]',
33178
- exportAs: 'kendoGridGroupBinding',
33179
- standalone: true
33180
- }]
33181
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: ContextService }, { type: GroupsService }]; }, propDecorators: { kendoGridGroupBinding: [{
33182
- type: Input,
33183
- args: ["kendoGridGroupBinding"]
33184
- }], sort: [{
33185
- type: Input
33186
- }], filter: [{
33187
- type: Input
33188
- }], group: [{
33189
- type: Input
33190
- }] } });
33191
-
33192
33195
  /**
33193
33196
  * Represents the Kendo UI GridSpacer component for Angular.
33194
33197
  * Used to give additional white space between the Pager inner elements,
@@ -33841,6 +33844,12 @@ class UndoRedoStack {
33841
33844
  this.currentNode = this.currentNode.previous;
33842
33845
  return this.currentNode.state;
33843
33846
  }
33847
+ peekNext() {
33848
+ return this.currentNode.next?.state || null;
33849
+ }
33850
+ peekPrev() {
33851
+ return this.currentNode.previous?.state || null;
33852
+ }
33844
33853
  /**
33845
33854
  * Performs a redo operation, moving to the next state
33846
33855
  * @returns The next state or null if can't redo
@@ -33963,7 +33972,6 @@ class UndoRedoService {
33963
33972
  onUndo = new Subject();
33964
33973
  onRedo = new Subject();
33965
33974
  stackEndReached = new Subject();
33966
- setState = new Subject();
33967
33975
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
33968
33976
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService });
33969
33977
  }
@@ -33987,11 +33995,17 @@ class UndoRedoDirective {
33987
33995
  editService;
33988
33996
  undoRedoService;
33989
33997
  changeNotification;
33998
+ ctx;
33999
+ localDataChangesService;
33990
34000
  /**
33991
34001
  * Sets the maximum number of actions to keep in the undo-redo stack.
33992
34002
  * @default 10
33993
34003
  */
33994
34004
  maxStoredStates = 10;
34005
+ /**
34006
+ * Defines the property name of the data item unique key that will be used to identify the items when performing undo-redo actions.
34007
+ */
34008
+ itemIdKey;
33995
34009
  /**
33996
34010
  * Fires when you perform the undo action. Provides the Grid state to apply.
33997
34011
  */
@@ -34009,11 +34023,13 @@ class UndoRedoDirective {
34009
34023
  stack;
34010
34024
  subs = new Subscription();
34011
34025
  addToState = true;
34012
- constructor(host, editService, undoRedoService, changeNotification) {
34026
+ constructor(host, editService, undoRedoService, changeNotification, ctx, localDataChangesService) {
34013
34027
  this.host = host;
34014
34028
  this.editService = editService;
34015
34029
  this.undoRedoService = undoRedoService;
34016
34030
  this.changeNotification = changeNotification;
34031
+ this.ctx = ctx;
34032
+ this.localDataChangesService = localDataChangesService;
34017
34033
  this.host.undoRedoService = this.undoRedoService;
34018
34034
  }
34019
34035
  ngOnInit() {
@@ -34025,7 +34041,7 @@ class UndoRedoDirective {
34025
34041
  sort: this.host.sort,
34026
34042
  filter: this.host.filter,
34027
34043
  group: this.host.group
34028
- }, gridState: structuredClone(this.host.currentState)
34044
+ }, gridState: this.host.currentState
34029
34045
  });
34030
34046
  this.subs = this.host.gridStateChange.subscribe((state) => {
34031
34047
  if (this.addToState) {
@@ -34037,7 +34053,7 @@ class UndoRedoDirective {
34037
34053
  filter: state.filter,
34038
34054
  group: state.group
34039
34055
  },
34040
- gridState: structuredClone(state)
34056
+ gridState: state
34041
34057
  });
34042
34058
  }
34043
34059
  let stackEndPointReached;
@@ -34050,36 +34066,72 @@ class UndoRedoDirective {
34050
34066
  this.undoRedoService.stackEndReached.next(stackEndPointReached);
34051
34067
  });
34052
34068
  this.subs.add(this.editService.changes
34053
- .pipe(filter(event => event.action === 'save' || event.action === 'remove'), tap(event => this.undoRedoService.originalEvent = event))
34069
+ .pipe(filter((event) => event.action === 'save' || event.action === 'remove'))
34054
34070
  .subscribe(event => {
34055
34071
  this.stack.add({
34056
- originalEvent: event,
34057
- gridState: structuredClone(this.host.currentState)
34072
+ originalEvent: { ...event, dataItem: structuredClone(event.dataItem) },
34073
+ gridState: this.host.currentState
34058
34074
  });
34059
34075
  this.addToState = false;
34060
34076
  this.host.gridStateChange.emit(this.stack.current.gridState);
34061
34077
  this.addToState = true;
34062
34078
  this.updateUndoRedoDisabled();
34063
34079
  }));
34064
- this.subs.add(this.changeNotification.changes.subscribe(() => this.stack.current.gridState = this.host.currentState));
34080
+ this.subs.add(this.changeNotification.changes.subscribe(() => {
34081
+ if (!this.ctx.dataBindingDirective) {
34082
+ this.stack.current.gridState = this.host.currentState;
34083
+ }
34084
+ }));
34065
34085
  ['Undo', 'Redo'].forEach((action) => {
34066
34086
  this.subs.add(this.undoRedoService[`on${action}`].subscribe(() => {
34067
34087
  if (!this.stack[`can${action}`]) {
34068
34088
  return;
34069
34089
  }
34070
- this.stack[`${action.toLowerCase()}`]();
34090
+ let eventData;
34091
+ if (action === 'Undo') {
34092
+ const isSaveOrRemove = this.stack.current.originalEvent.action === 'save' || this.stack.current.originalEvent.action === 'remove';
34093
+ eventData = isSaveOrRemove ? this.stack.current : this.stack.peekPrev();
34094
+ }
34095
+ else {
34096
+ eventData = this.stack.peekNext();
34097
+ }
34098
+ const event = new UndoRedoEvent(eventData);
34071
34099
  if (hasObservers(this[`on${action}`])) {
34072
- const event = new UndoRedoEvent(this.stack.current);
34073
34100
  this[`on${action}`].emit(event);
34074
34101
  if (event.isDefaultPrevented()) {
34075
34102
  return;
34076
34103
  }
34077
34104
  }
34105
+ this.stack[`${action.toLowerCase()}`]();
34078
34106
  this.updateUndoRedoDisabled();
34079
- this.host.loadState(this.stack.current.gridState);
34107
+ const originalAction = event.originalEvent.action;
34108
+ const isLocalData = isPresent$1(this.ctx?.dataBindingDirective);
34109
+ if (!isLocalData) {
34110
+ return;
34111
+ }
34112
+ const isSaveOrRemove = originalAction === 'save' || originalAction === 'remove';
34113
+ if (isSaveOrRemove) {
34114
+ if (originalAction === 'save') {
34115
+ const stateItem = this.getGridDataItems(this.stack.current.gridState.currentData).find(item => item[this.itemIdKey] === event.originalEvent.dataItem[this.itemIdKey]);
34116
+ Object.assign(event.originalEvent.originalDataItem, stateItem);
34117
+ }
34118
+ else if (action === 'Undo') {
34119
+ this.localDataChangesService?.data.splice(event.originalEvent.rowIndex, 0, event.originalEvent.dataItem);
34120
+ }
34121
+ else {
34122
+ this.localDataChangesService?.data.splice(event.originalEvent.rowIndex, 1);
34123
+ }
34124
+ this.localDataChangesService?.changes.emit();
34125
+ }
34126
+ else {
34127
+ this.host.loadState({ ...this.stack.current.gridState, currentData: null });
34128
+ if (this.isDataStateChangeEvent(event.originalEvent)) {
34129
+ const { skip, take, sort, filter, group } = this.stack.current.gridState;
34130
+ this.host.dataStateChange.emit({ skip, take, sort, filter, group });
34131
+ }
34132
+ }
34080
34133
  }));
34081
34134
  });
34082
- this.subs.add(this.undoRedoService.setState.subscribe((state) => this.stack.add({ originalEvent: 'dataChange', gridState: state })));
34083
34135
  }
34084
34136
  ngOnDestroy() {
34085
34137
  this.stack.clear();
@@ -34121,8 +34173,15 @@ class UndoRedoDirective {
34121
34173
  }
34122
34174
  this.undoRedoService.stackEndReached.next(false);
34123
34175
  }
34124
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, deps: [{ token: GridComponent }, { token: EditService }, { token: UndoRedoService }, { token: ChangeNotificationService }], target: i0.ɵɵFactoryTarget.Directive });
34125
- 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 });
34176
+ getGridDataItems(data) {
34177
+ return Array.isArray(data) ? data.flatMap(recursiveFlatMap) :
34178
+ data.data.flatMap(recursiveFlatMap);
34179
+ }
34180
+ isDataStateChangeEvent(event) {
34181
+ return event && ['skip', 'take', 'sort', 'filter', 'group'].some(prop => prop in event);
34182
+ }
34183
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, deps: [{ token: GridComponent }, { token: EditService }, { token: UndoRedoService }, { token: ChangeNotificationService }, { token: ContextService }, { token: LocalDataChangesService }], target: i0.ɵɵFactoryTarget.Directive });
34184
+ 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 });
34126
34185
  }
34127
34186
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, decorators: [{
34128
34187
  type: Directive,
@@ -34132,7 +34191,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
34132
34191
  exportAs: 'kendoGridUndoRedo',
34133
34192
  providers: [UndoRedoService]
34134
34193
  }]
34135
- }], ctorParameters: function () { return [{ type: GridComponent }, { type: EditService }, { type: UndoRedoService }, { type: ChangeNotificationService }]; }, propDecorators: { maxStoredStates: [{
34194
+ }], ctorParameters: function () { return [{ type: GridComponent }, { type: EditService }, { type: UndoRedoService }, { type: ChangeNotificationService }, { type: ContextService }, { type: LocalDataChangesService }]; }, propDecorators: { maxStoredStates: [{
34195
+ type: Input
34196
+ }], itemIdKey: [{
34136
34197
  type: Input
34137
34198
  }], onUndo: [{
34138
34199
  type: Output,