@progress/kendo-angular-grid 19.2.0-develop.4 → 19.2.0-develop.6

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.
@@ -868,7 +868,7 @@ class ContextService {
868
868
  topToolbarNavigation;
869
869
  bottomToolbarNavigation;
870
870
  navigable;
871
- groupBindingDirective;
871
+ dataBindingDirective;
872
872
  constructor(renderer, localization) {
873
873
  this.renderer = renderer;
874
874
  this.localization = localization;
@@ -16675,7 +16675,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
16675
16675
  */
16676
16676
  class CellSelectionAggregateService {
16677
16677
  ctx;
16678
- dataChanges;
16679
16678
  columnInfoService;
16680
16679
  selectedItems = [];
16681
16680
  groupedAggregates = { dates: [], numbers: [], booleans: [] };
@@ -16691,9 +16690,8 @@ class CellSelectionAggregateService {
16691
16690
  latest: null
16692
16691
  };
16693
16692
  sub = new Subscription();
16694
- constructor(ctx, dataChanges, columnInfoService) {
16693
+ constructor(ctx, columnInfoService) {
16695
16694
  this.ctx = ctx;
16696
- this.dataChanges = dataChanges;
16697
16695
  this.columnInfoService = columnInfoService;
16698
16696
  }
16699
16697
  ngOnDestroy() {
@@ -16854,12 +16852,12 @@ class CellSelectionAggregateService {
16854
16852
  this.aggregates['isFalse'] = this.aggregates['isTrue'] = null;
16855
16853
  this.aggregates['earliest'] = this.aggregates['latest'] = null;
16856
16854
  }
16857
- 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 });
16858
16856
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService });
16859
16857
  }
16860
16858
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellSelectionAggregateService, decorators: [{
16861
16859
  type: Injectable
16862
- }], ctorParameters: function () { return [{ type: ContextService }, { type: LocalDataChangesService }, { type: ColumnInfoService }]; } });
16860
+ }], ctorParameters: function () { return [{ type: ContextService }, { type: ColumnInfoService }]; } });
16863
16861
 
16864
16862
  /**
16865
16863
  * @hidden
@@ -21216,8 +21214,8 @@ const packageMetadata = {
21216
21214
  productName: 'Kendo UI for Angular',
21217
21215
  productCode: 'KENDOUIANGULAR',
21218
21216
  productCodes: ['KENDOUIANGULAR'],
21219
- publishDate: 1750933458,
21220
- version: '19.2.0-develop.4',
21217
+ publishDate: 1751009984,
21218
+ version: '19.2.0-develop.6',
21221
21219
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
21222
21220
  };
21223
21221
 
@@ -27647,6 +27645,538 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
27647
27645
  args: [GroupToolbarToolComponent]
27648
27646
  }] } });
27649
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
+
27650
28180
  const createControl = (source) => (acc, key) => {
27651
28181
  acc[key] = new FormControl(source[key]);
27652
28182
  return acc;
@@ -29127,12 +29657,12 @@ class GridComponent {
29127
29657
  this.sort = state.sort;
29128
29658
  this.group = state.group;
29129
29659
  this.filter = state.filter;
29130
- this.group = state.group;
29131
29660
  this.skip = state.skip;
29132
29661
  this.pageSize = state.take;
29133
- this.data = state.currentData;
29134
- this.changeNotification.notify();
29135
- this.changeDetectorRef.detectChanges();
29662
+ if (state.currentData) {
29663
+ this.data = state.currentData;
29664
+ }
29665
+ this.changeDetectorRef.markForCheck();
29136
29666
  }
29137
29667
  traverseColumns(columns, callback) {
29138
29668
  columns.forEach((column) => {
@@ -29821,8 +30351,8 @@ class GridComponent {
29821
30351
  }
29822
30352
  if (this.groupsService.isExpanded({ groupIndex: index }) !== expand) {
29823
30353
  this.groupsService.toggleRow({ index }, false);
29824
- if (this.ctx.groupBindingDirective) {
29825
- 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 });
29826
30356
  }
29827
30357
  }
29828
30358
  }
@@ -31760,213 +32290,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
31760
32290
  }]
31761
32291
  }], ctorParameters: function () { return [{ type: i1$2.LocalizationService }]; } });
31762
32292
 
31763
- /**
31764
- * A directive that handles in-memory data operations like [paging]({% slug paging_grid %}),
31765
- * [sorting]({% slug sorting_grid %}), and [grouping]({% slug grouping_grid %}).
31766
- *
31767
- * Use this directive with local data and enable the Grid data operations with minimal configuration.
31768
- * ([More information and examples]({% slug local_data_grid %}#toc-using-the-data-binding-directive)).
31769
- *
31770
- * @example
31771
- * ```html
31772
- * <kendo-grid [kendoGridBinding]="gridData"></kendo-grid>
31773
- * ```
31774
- * @remarks
31775
- * Applied to: {@link GridComponent}.
31776
- */
31777
- class DataBindingDirective {
31778
- grid;
31779
- changeDetector;
31780
- localDataChangesService;
31781
- rowReorderService;
31782
- /**
31783
- * Sets the number of records to skip in the Grid.
31784
- *
31785
- * @default 0
31786
- */
31787
- set skip(value) {
31788
- if (!isPresent(value)) {
31789
- value = 0;
31790
- }
31791
- this.grid.skip = this.state.skip = value;
31792
- if (this.rowReorderService) {
31793
- this.rowReorderService.skip = value;
31794
- }
31795
- }
31796
- /**
31797
- * Sets the sort descriptors for the Grid data.
31798
- *
31799
- */
31800
- set sort(value) {
31801
- this.grid.sort = this.state.sort = value;
31802
- }
31803
- /**
31804
- * Sets the filter descriptor for the Grid data.
31805
- *
31806
- */
31807
- set filter(value) {
31808
- this.grid.filter = this.state.filter = value;
31809
- }
31810
- /**
31811
- * Sets the page size for the Grid pager.
31812
- *
31813
- */
31814
- set pageSize(value) {
31815
- this.grid.pageSize = this.state.take = value;
31816
- }
31817
- /**
31818
- * Sets the group descriptors for the Grid data.
31819
- *
31820
- */
31821
- set group(value) {
31822
- this.grid.group = this.state.group = value;
31823
- }
31824
- /**
31825
- * Sets the data array for the Grid.
31826
- *
31827
- */
31828
- set data(value) {
31829
- this.originalData = value || [];
31830
- if (this.localDataChangesService) {
31831
- this.localDataChangesService.data = value;
31832
- }
31833
- this.dataChanged = true;
31834
- }
31835
- state = {
31836
- skip: 0
31837
- };
31838
- originalData = [];
31839
- dataChanged;
31840
- stateChangeSubscription;
31841
- dataChangedSubscription;
31842
- rowReorderSubscription;
31843
- constructor(grid, changeDetector, localDataChangesService, rowReorderService) {
31844
- this.grid = grid;
31845
- this.changeDetector = changeDetector;
31846
- this.localDataChangesService = localDataChangesService;
31847
- this.rowReorderService = rowReorderService;
31848
- if (localDataChangesService) {
31849
- this.dataChangedSubscription = this.localDataChangesService.changes.subscribe(this.rebind.bind(this));
31850
- }
31851
- }
31852
- /**
31853
- * @hidden
31854
- */
31855
- ngOnInit() {
31856
- this.applyState(this.state);
31857
- this.stateChangeSubscription = this.grid
31858
- .dataStateChange
31859
- .subscribe(this.onStateChange.bind(this));
31860
- if (this.rowReorderService) {
31861
- this.rowReorderSubscription = this.grid
31862
- .rowReorder
31863
- .subscribe(this.onRowReorder.bind(this));
31864
- }
31865
- }
31866
- /**
31867
- * @hidden
31868
- */
31869
- ngOnDestroy() {
31870
- if (this.stateChangeSubscription) {
31871
- this.stateChangeSubscription.unsubscribe();
31872
- }
31873
- if (this.dataChangedSubscription) {
31874
- this.dataChangedSubscription.unsubscribe();
31875
- }
31876
- if (this.rowReorderSubscription) {
31877
- this.rowReorderSubscription.unsubscribe();
31878
- }
31879
- }
31880
- /**
31881
- * @hidden
31882
- */
31883
- ngOnChanges(changes) {
31884
- if (anyChanged(["pageSize", "skip", "sort", "group", "filter"], changes)) {
31885
- this.rebind();
31886
- }
31887
- }
31888
- ngDoCheck() {
31889
- if (this.dataChanged) {
31890
- this.updateGridData();
31891
- }
31892
- }
31893
- /**
31894
- * @hidden
31895
- */
31896
- onStateChange(state) {
31897
- this.applyState(state);
31898
- this.rebind();
31899
- }
31900
- /**
31901
- * @hidden
31902
- */
31903
- onRowReorder(ev) {
31904
- this.rowReorderService.reorderRows(ev, this.originalData);
31905
- this.rebind();
31906
- }
31907
- /**
31908
- * @hidden
31909
- */
31910
- rebind() {
31911
- this.data = this.originalData;
31912
- this.updateGridData();
31913
- this.notifyDataChange();
31914
- }
31915
- /**
31916
- * Notifies the Grid that its data has changed.
31917
- */
31918
- notifyDataChange() {
31919
- this.grid.onDataChange();
31920
- if (this.changeDetector) {
31921
- this.changeDetector.markForCheck();
31922
- }
31923
- }
31924
- process(state) {
31925
- if (this.grid.isVirtual && (!isPresent(state.take) || state.take === 0)) {
31926
- return {
31927
- data: [],
31928
- total: this.originalData?.length || 0
31929
- };
31930
- }
31931
- return process(this.originalData, state);
31932
- }
31933
- applyState({ skip, take, sort, group, filter }) {
31934
- this.skip = skip;
31935
- this.pageSize = take;
31936
- this.sort = sort;
31937
- this.group = group;
31938
- this.filter = filter;
31939
- }
31940
- updateGridData() {
31941
- this.grid.data = this.process(this.state);
31942
- this.grid.updateNavigationMetadata();
31943
- this.dataChanged = false;
31944
- }
31945
- 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 });
31946
- 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 });
31947
- }
31948
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataBindingDirective, decorators: [{
31949
- type: Directive,
31950
- args: [{
31951
- selector: '[kendoGridBinding]',
31952
- exportAs: 'kendoGridBinding',
31953
- standalone: true
31954
- }]
31955
- }], ctorParameters: function () { return [{ type: GridComponent }, { type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: RowReorderService }]; }, propDecorators: { skip: [{
31956
- type: Input
31957
- }], sort: [{
31958
- type: Input
31959
- }], filter: [{
31960
- type: Input
31961
- }], pageSize: [{
31962
- type: Input
31963
- }], group: [{
31964
- type: Input
31965
- }], data: [{
31966
- type: Input,
31967
- args: ["kendoGridBinding"]
31968
- }] } });
31969
-
31970
32293
  /**
31971
32294
  * Stores the row selection state of the Grid in memory
31972
32295
  * ([see example]({% slug selection_grid %}#toc-toggling-the-selection-functionality)).
@@ -32869,330 +33192,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
32869
33192
  type: Input
32870
33193
  }] } });
32871
33194
 
32872
- const hasGroups = (items) => items && items.length && items[0].field && items[0].items;
32873
- const groupDescriptorsPresent = (descriptors) => isPresent(descriptors) && descriptors.length > 0;
32874
- const processGroups = (data, state) => process(data, state).data;
32875
- const removeParentDescriptors = (parents, owner) => g => g.field !== owner.field && !parents.some(y => y.field === g.field);
32876
- const findGroup = (groupIndex, groups) => {
32877
- const parents = [];
32878
- return {
32879
- group: groupIndex.split("_").reduce((acc, x) => {
32880
- const idx = parseInt(x, 10);
32881
- if (acc.items) {
32882
- parents.push(acc);
32883
- return acc.items[idx];
32884
- }
32885
- return isArray(acc) ? acc[idx] : acc;
32886
- }, groups),
32887
- parents
32888
- };
32889
- };
32890
- const findChildren = (data, parents) => {
32891
- const filters = parents.map(p => ({ field: p.field, operator: "eq", value: p.value }));
32892
- return filterBy(data, {
32893
- filters: filters,
32894
- logic: "and"
32895
- });
32896
- };
32897
- /**
32898
- * @hidden
32899
- */
32900
- const count = (groups, includeFooters = false) => (groups.reduce((acc, group) => {
32901
- if (!group.skipHeader) {
32902
- acc++;
32903
- }
32904
- if (group.items) {
32905
- const children = count(group.items, includeFooters);
32906
- if (includeFooters && children && !group.hideFooter) {
32907
- acc++;
32908
- }
32909
- acc += children;
32910
- }
32911
- return acc;
32912
- }, 0));
32913
- /**
32914
- * @hidden
32915
- */
32916
- const noDescriptors = (descriptors) => !isPresent(descriptors) || !descriptors.length;
32917
- /**
32918
- * @hidden
32919
- */
32920
- const slice = (groups, skip, take, includeFooters = false) => {
32921
- if (!isPresent(take)) {
32922
- return groups;
32923
- }
32924
- const result = [];
32925
- for (let idx = 0, length = groups.length; idx < length; idx++) {
32926
- if (take <= 0) {
32927
- break;
32928
- }
32929
- const group = groups[idx];
32930
- const groupItems = group.items;
32931
- let itemCount = count(groupItems, includeFooters);
32932
- if (includeFooters && groupItems.length) {
32933
- itemCount++;
32934
- }
32935
- const skipHeader = skip > 0;
32936
- if (skip) {
32937
- skip--;
32938
- if (itemCount && skip >= itemCount) {
32939
- skip -= itemCount;
32940
- continue;
32941
- }
32942
- }
32943
- if (!skipHeader || itemCount) {
32944
- const items = [];
32945
- let hideFooter = true;
32946
- if (!skipHeader) {
32947
- take--;
32948
- }
32949
- if (take) {
32950
- if (hasGroups(groupItems)) {
32951
- const children = slice(groupItems, skip, take, includeFooters);
32952
- items.push(...children);
32953
- take -= count(children, includeFooters);
32954
- }
32955
- else {
32956
- items.push(...groupItems.slice(skip, Math.min(skip + take, groupItems.length)));
32957
- take -= items.length;
32958
- }
32959
- if (take && includeFooters) {
32960
- hideFooter = false;
32961
- take--;
32962
- }
32963
- skip = 0;
32964
- }
32965
- result.push({
32966
- aggregates: group.aggregates,
32967
- field: group.field,
32968
- hideFooter,
32969
- items,
32970
- offset: idx,
32971
- skipHeader,
32972
- value: group.value
32973
- });
32974
- }
32975
- }
32976
- return result;
32977
- };
32978
- const skippedHeaders = (groupItem) => {
32979
- let total = 0;
32980
- while (groupItem) {
32981
- if (groupItem.skipHeader) {
32982
- total++;
32983
- }
32984
- groupItem = groupItem.items && groupItem.items[0] || null;
32985
- }
32986
- return total;
32987
- };
32988
- /**
32989
- * A directive which encapsulates the in-memory handling of grouping with virtual scrolling.
32990
- * @remarks
32991
- * Applied to: {@link GridComponent}.
32992
- */
32993
- class GroupBindingDirective extends DataBindingDirective {
32994
- groupsService;
32995
- /**
32996
- * The array of data which will be used to populate the Grid.
32997
- */
32998
- set kendoGridGroupBinding(value) {
32999
- this.groups = null;
33000
- this.grid.resetGroupsState();
33001
- this.data = value;
33002
- }
33003
- /**
33004
- * @hidden
33005
- */
33006
- set data(value) {
33007
- this.originalData = value || [];
33008
- this.dataChanged = true;
33009
- }
33010
- /**
33011
- * Defines the descriptors by which the data will be sorted.
33012
- */
33013
- set sort(value) {
33014
- const noCurrentDescriptors = noDescriptors(this.state.sort);
33015
- const noIncomingDescriptors = noDescriptors(value);
33016
- const clear = this.state.sort !== value && !(noCurrentDescriptors && noIncomingDescriptors);
33017
- this.grid.sort = this.state.sort = value;
33018
- if (clear) {
33019
- this.groups = null;
33020
- this.grid.resetGroupsState();
33021
- }
33022
- }
33023
- /**
33024
- * Defines the descriptor by which the data will be filtered.
33025
- */
33026
- set filter(value) {
33027
- const clear = diffFilters(this.state.filter, value);
33028
- if (clear) {
33029
- this.state.filter = value;
33030
- this.grid.filter = cloneFilters(value);
33031
- this.groups = null;
33032
- this.grid.resetGroupsState();
33033
- }
33034
- }
33035
- /**
33036
- * Defines the descriptors by which the data will be grouped.
33037
- */
33038
- set group(value) {
33039
- // don't clear if no groups are present in previous and current value
33040
- const groupsPresent = groupDescriptorsPresent(this.state.group) || groupDescriptorsPresent(value);
33041
- const clear = this.state.group !== value && groupsPresent;
33042
- this.grid.group = this.state.group = value;
33043
- if (clear) {
33044
- this.groups = null;
33045
- this.grid.resetGroupsState();
33046
- this.skip = 0;
33047
- }
33048
- }
33049
- groups;
33050
- gridSubs = new Subscription();
33051
- constructor(changeDetector, localDataChangesService, ctxService, groupsService) {
33052
- super(ctxService.grid, changeDetector, localDataChangesService);
33053
- this.groupsService = groupsService;
33054
- ctxService.groupBindingDirective = this;
33055
- }
33056
- ngOnInit() {
33057
- super.ngOnInit();
33058
- this.gridSubs.add(this.grid.groupExpand.subscribe(this.groupExpand.bind(this)));
33059
- this.gridSubs.add(this.grid.groupCollapse.subscribe(this.groupCollapse.bind(this)));
33060
- }
33061
- ngAfterContentInit() {
33062
- if (isDevMode() && this.grid.isGroupExpanded) {
33063
- throw new Error(GridConfigurationErrorMessages.groupBindingDirectives);
33064
- }
33065
- }
33066
- ngOnDestroy() {
33067
- this.gridSubs.unsubscribe();
33068
- }
33069
- /**
33070
- * @hidden
33071
- */
33072
- toggleAll(expand) {
33073
- this.skip = 0;
33074
- this.grid.scrollTo({ row: 0, column: 0 });
33075
- this.groups.forEach((gr, idx) => {
33076
- const expanded = this.groupsService.isExpanded({
33077
- group: gr,
33078
- groupIndex: idx.toString(),
33079
- parentGroup: undefined
33080
- });
33081
- const performToggle = (expand && !expanded) || (!expand && expanded);
33082
- if (performToggle) {
33083
- this.grid.groupsService.toggleRow({
33084
- type: 'group',
33085
- data: gr,
33086
- index: idx.toString(),
33087
- level: 0,
33088
- parentGroup: undefined
33089
- });
33090
- this[expand ? 'groupExpand' : 'groupCollapse']({ groupIndex: idx.toString() });
33091
- }
33092
- });
33093
- }
33094
- /**
33095
- * Collapses all expanded root level groups.
33096
- */
33097
- collapseAll() {
33098
- this.toggleAll(false);
33099
- }
33100
- /**
33101
- * Expands all expanded root level groups.
33102
- */
33103
- expandAll() {
33104
- this.toggleAll(true);
33105
- }
33106
- /**
33107
- * @hidden
33108
- */
33109
- groupExpand({ groupIndex }) {
33110
- const { group, parents } = findGroup(groupIndex, this.groups);
33111
- if (!group) {
33112
- return;
33113
- }
33114
- this.groupsService.expandChildren(groupIndex);
33115
- if (!group.items.length) {
33116
- const descriptors = this.state.group.filter(removeParentDescriptors(parents, group));
33117
- const children = findChildren(this.originalData, parents.concat(group));
33118
- group.items = processGroups(children, {
33119
- filter: this.state.filter,
33120
- group: descriptors,
33121
- sort: this.state.sort
33122
- });
33123
- }
33124
- this.grid.data = this.dataResult(this.state.skip, this.state.take);
33125
- }
33126
- /**
33127
- * @hidden
33128
- */
33129
- groupCollapse({ groupIndex }) {
33130
- const { group } = findGroup(groupIndex, this.groups);
33131
- if (group) {
33132
- group.items = [];
33133
- }
33134
- else {
33135
- return;
33136
- }
33137
- this.grid.data = this.dataResult(this.state.skip, this.state.take);
33138
- }
33139
- process(state) {
33140
- if (state.group && state.group.length) {
33141
- const groups = this.processGroups(state);
33142
- this.grid.skip -= skippedHeaders(groups.data[0]);
33143
- return groups;
33144
- }
33145
- else {
33146
- this.groups = null;
33147
- }
33148
- return super.process(state);
33149
- }
33150
- processGroups(state) {
33151
- if (!this.groups || !this.groups.length) {
33152
- this.groups = processGroups(this.originalData, {
33153
- filter: state.filter,
33154
- group: state.group,
33155
- sort: state.sort
33156
- });
33157
- }
33158
- return this.dataResult(state.skip, state.take);
33159
- }
33160
- dataResult(skip, take) {
33161
- const includeFooters = this.grid.showGroupFooters;
33162
- return {
33163
- data: slice(this.groups, skip, take, includeFooters),
33164
- total: count(this.groups, includeFooters)
33165
- };
33166
- }
33167
- applyState({ skip, take, sort, group, filter }) {
33168
- this.skip = skip;
33169
- this.state.take = take;
33170
- // this.pageSize = take; // do need to update take as the process with slice correctly
33171
- this.sort = sort;
33172
- this.group = group;
33173
- this.filter = filter;
33174
- }
33175
- 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 });
33176
- 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 });
33177
- }
33178
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GroupBindingDirective, decorators: [{
33179
- type: Directive,
33180
- args: [{
33181
- selector: '[kendoGridGroupBinding]',
33182
- exportAs: 'kendoGridGroupBinding',
33183
- standalone: true
33184
- }]
33185
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: LocalDataChangesService }, { type: ContextService }, { type: GroupsService }]; }, propDecorators: { kendoGridGroupBinding: [{
33186
- type: Input,
33187
- args: ["kendoGridGroupBinding"]
33188
- }], sort: [{
33189
- type: Input
33190
- }], filter: [{
33191
- type: Input
33192
- }], group: [{
33193
- type: Input
33194
- }] } });
33195
-
33196
33195
  /**
33197
33196
  * Represents the Kendo UI GridSpacer component for Angular.
33198
33197
  * Used to give additional white space between the Pager inner elements,
@@ -33845,6 +33844,12 @@ class UndoRedoStack {
33845
33844
  this.currentNode = this.currentNode.previous;
33846
33845
  return this.currentNode.state;
33847
33846
  }
33847
+ peekNext() {
33848
+ return this.currentNode.next?.state || null;
33849
+ }
33850
+ peekPrev() {
33851
+ return this.currentNode.previous?.state || null;
33852
+ }
33848
33853
  /**
33849
33854
  * Performs a redo operation, moving to the next state
33850
33855
  * @returns The next state or null if can't redo
@@ -33967,7 +33972,6 @@ class UndoRedoService {
33967
33972
  onUndo = new Subject();
33968
33973
  onRedo = new Subject();
33969
33974
  stackEndReached = new Subject();
33970
- setState = new Subject();
33971
33975
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
33972
33976
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoService });
33973
33977
  }
@@ -33991,11 +33995,17 @@ class UndoRedoDirective {
33991
33995
  editService;
33992
33996
  undoRedoService;
33993
33997
  changeNotification;
33998
+ ctx;
33999
+ localDataChangesService;
33994
34000
  /**
33995
34001
  * Sets the maximum number of actions to keep in the undo-redo stack.
33996
34002
  * @default 10
33997
34003
  */
33998
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;
33999
34009
  /**
34000
34010
  * Fires when you perform the undo action. Provides the Grid state to apply.
34001
34011
  */
@@ -34013,11 +34023,13 @@ class UndoRedoDirective {
34013
34023
  stack;
34014
34024
  subs = new Subscription();
34015
34025
  addToState = true;
34016
- constructor(host, editService, undoRedoService, changeNotification) {
34026
+ constructor(host, editService, undoRedoService, changeNotification, ctx, localDataChangesService) {
34017
34027
  this.host = host;
34018
34028
  this.editService = editService;
34019
34029
  this.undoRedoService = undoRedoService;
34020
34030
  this.changeNotification = changeNotification;
34031
+ this.ctx = ctx;
34032
+ this.localDataChangesService = localDataChangesService;
34021
34033
  this.host.undoRedoService = this.undoRedoService;
34022
34034
  }
34023
34035
  ngOnInit() {
@@ -34029,7 +34041,7 @@ class UndoRedoDirective {
34029
34041
  sort: this.host.sort,
34030
34042
  filter: this.host.filter,
34031
34043
  group: this.host.group
34032
- }, gridState: structuredClone(this.host.currentState)
34044
+ }, gridState: this.host.currentState
34033
34045
  });
34034
34046
  this.subs = this.host.gridStateChange.subscribe((state) => {
34035
34047
  if (this.addToState) {
@@ -34041,7 +34053,7 @@ class UndoRedoDirective {
34041
34053
  filter: state.filter,
34042
34054
  group: state.group
34043
34055
  },
34044
- gridState: structuredClone(state)
34056
+ gridState: state
34045
34057
  });
34046
34058
  }
34047
34059
  let stackEndPointReached;
@@ -34054,36 +34066,72 @@ class UndoRedoDirective {
34054
34066
  this.undoRedoService.stackEndReached.next(stackEndPointReached);
34055
34067
  });
34056
34068
  this.subs.add(this.editService.changes
34057
- .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'))
34058
34070
  .subscribe(event => {
34059
34071
  this.stack.add({
34060
- originalEvent: event,
34061
- gridState: structuredClone(this.host.currentState)
34072
+ originalEvent: { ...event, dataItem: structuredClone(event.dataItem) },
34073
+ gridState: this.host.currentState
34062
34074
  });
34063
34075
  this.addToState = false;
34064
34076
  this.host.gridStateChange.emit(this.stack.current.gridState);
34065
34077
  this.addToState = true;
34066
34078
  this.updateUndoRedoDisabled();
34067
34079
  }));
34068
- 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
+ }));
34069
34085
  ['Undo', 'Redo'].forEach((action) => {
34070
34086
  this.subs.add(this.undoRedoService[`on${action}`].subscribe(() => {
34071
34087
  if (!this.stack[`can${action}`]) {
34072
34088
  return;
34073
34089
  }
34074
- 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);
34075
34099
  if (hasObservers(this[`on${action}`])) {
34076
- const event = new UndoRedoEvent(this.stack.current);
34077
34100
  this[`on${action}`].emit(event);
34078
34101
  if (event.isDefaultPrevented()) {
34079
34102
  return;
34080
34103
  }
34081
34104
  }
34105
+ this.stack[`${action.toLowerCase()}`]();
34082
34106
  this.updateUndoRedoDisabled();
34083
- 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
+ }
34084
34133
  }));
34085
34134
  });
34086
- this.subs.add(this.undoRedoService.setState.subscribe((state) => this.stack.add({ originalEvent: 'dataChange', gridState: state })));
34087
34135
  }
34088
34136
  ngOnDestroy() {
34089
34137
  this.stack.clear();
@@ -34125,8 +34173,15 @@ class UndoRedoDirective {
34125
34173
  }
34126
34174
  this.undoRedoService.stackEndReached.next(false);
34127
34175
  }
34128
- 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 });
34129
- 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 });
34130
34185
  }
34131
34186
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UndoRedoDirective, decorators: [{
34132
34187
  type: Directive,
@@ -34136,7 +34191,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
34136
34191
  exportAs: 'kendoGridUndoRedo',
34137
34192
  providers: [UndoRedoService]
34138
34193
  }]
34139
- }], 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: [{
34140
34197
  type: Input
34141
34198
  }], onUndo: [{
34142
34199
  type: Output,