@syncfusion/ej2-treegrid 31.2.12 → 32.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ej2-treegrid.min.js +1 -10
- package/dist/ej2-treegrid.umd.min.js +1 -10
- package/dist/ej2-treegrid.umd.min.js.map +1 -1
- package/dist/es6/ej2-treegrid.es2015.js +1069 -324
- package/dist/es6/ej2-treegrid.es2015.js.map +1 -1
- package/dist/es6/ej2-treegrid.es5.js +1075 -327
- package/dist/es6/ej2-treegrid.es5.js.map +1 -1
- package/dist/global/ej2-treegrid.min.js +1 -10
- package/dist/global/ej2-treegrid.min.js.map +1 -1
- package/dist/global/index.d.ts +0 -9
- package/package.json +5 -5
- package/src/treegrid/actions/batch-edit.js +22 -4
- package/src/treegrid/actions/context-menu.d.ts +1 -0
- package/src/treegrid/actions/context-menu.js +16 -0
- package/src/treegrid/actions/crud-actions.js +12 -5
- package/src/treegrid/actions/edit.d.ts +4 -1
- package/src/treegrid/actions/edit.js +59 -3
- package/src/treegrid/actions/freeze-column.js +1 -1
- package/src/treegrid/actions/rowdragdrop.js +3 -0
- package/src/treegrid/actions/selection.d.ts +226 -8
- package/src/treegrid/actions/selection.js +759 -288
- package/src/treegrid/actions/summary.js +1 -1
- package/src/treegrid/actions/virtual-scroll.js +6 -3
- package/src/treegrid/base/data.js +2 -1
- package/src/treegrid/base/treegrid-model.d.ts +16 -0
- package/src/treegrid/base/treegrid.d.ts +50 -4
- package/src/treegrid/base/treegrid.js +158 -19
- package/src/treegrid/models/column.d.ts +24 -0
- package/src/treegrid/models/column.js +12 -0
- package/src/treegrid/renderer/virtual-tree-content-render.d.ts +5 -0
- package/src/treegrid/renderer/virtual-tree-content-render.js +24 -2
- package/styles/bds-lite.scss +17 -18
- package/styles/bds.scss +18 -19
- package/styles/bootstrap-dark-lite.scss +17 -18
- package/styles/bootstrap-dark.scss +18 -19
- package/styles/bootstrap-lite.scss +17 -18
- package/styles/bootstrap.scss +18 -19
- package/styles/bootstrap4-lite.scss +17 -18
- package/styles/bootstrap4.scss +18 -19
- package/styles/bootstrap5-dark-lite.scss +17 -18
- package/styles/bootstrap5-dark.scss +18 -19
- package/styles/bootstrap5-lite.scss +18 -18
- package/styles/bootstrap5.3-lite.css +81 -1
- package/styles/bootstrap5.3-lite.scss +18 -18
- package/styles/bootstrap5.3.css +81 -1
- package/styles/bootstrap5.3.scss +19 -19
- package/styles/bootstrap5.scss +19 -19
- package/styles/fabric-dark-lite.scss +18 -18
- package/styles/fabric-dark.scss +19 -19
- package/styles/fabric-lite.scss +18 -18
- package/styles/fabric.scss +19 -19
- package/styles/fluent-dark-lite.scss +18 -18
- package/styles/fluent-dark.scss +19 -19
- package/styles/fluent-lite.scss +18 -18
- package/styles/fluent.scss +19 -19
- package/styles/fluent2-lite.css +152 -4
- package/styles/fluent2-lite.scss +18 -18
- package/styles/fluent2.css +152 -4
- package/styles/fluent2.scss +19 -19
- package/styles/highcontrast-light-lite.scss +18 -18
- package/styles/highcontrast-light.scss +19 -19
- package/styles/highcontrast-lite.scss +18 -18
- package/styles/highcontrast.scss +19 -19
- package/styles/material-dark-lite.scss +18 -18
- package/styles/material-dark.scss +19 -19
- package/styles/material-lite.scss +17 -18
- package/styles/material.scss +18 -19
- package/styles/material3-dark-lite.css +140 -1
- package/styles/material3-dark-lite.scss +18 -18
- package/styles/material3-dark.css +140 -1
- package/styles/material3-dark.scss +19 -21
- package/styles/material3-lite.css +140 -1
- package/styles/material3-lite.scss +18 -18
- package/styles/material3.css +140 -1
- package/styles/material3.scss +19 -21
- package/styles/tailwind-dark-lite.scss +18 -18
- package/styles/tailwind-dark.scss +19 -19
- package/styles/tailwind-lite.scss +18 -18
- package/styles/tailwind.scss +19 -19
- package/styles/tailwind3-lite.css +119 -1
- package/styles/tailwind3-lite.scss +18 -18
- package/styles/tailwind3.css +119 -1
- package/styles/tailwind3.scss +19 -19
- package/styles/treegrid/_all.scss +2 -2
- package/styles/treegrid/_bds-definition.scss +2 -0
- package/styles/treegrid/_bigger.scss +2 -0
- package/styles/treegrid/_bootstrap-dark-definition.scss +2 -0
- package/styles/treegrid/_bootstrap-definition.scss +2 -0
- package/styles/treegrid/_bootstrap4-definition.scss +2 -0
- package/styles/treegrid/_bootstrap5-dark-definition.scss +26 -1
- package/styles/treegrid/_bootstrap5-definition.scss +2 -0
- package/styles/treegrid/_bootstrap5.3-definition.scss +2 -0
- package/styles/treegrid/_fabric-dark-definition.scss +2 -0
- package/styles/treegrid/_fabric-definition.scss +2 -0
- package/styles/treegrid/_fluent-dark-definition.scss +27 -1
- package/styles/treegrid/_fluent-definition.scss +2 -0
- package/styles/treegrid/_fluent2-definition.scss +2 -0
- package/styles/treegrid/_highcontrast-definition.scss +2 -0
- package/styles/treegrid/_highcontrast-light-definition.scss +2 -0
- package/styles/treegrid/_layout.scss +5 -2
- package/styles/treegrid/_material-dark-definition.scss +2 -0
- package/styles/treegrid/_material-definition.scss +2 -0
- package/styles/treegrid/_material3-dark-definition.scss +26 -1
- package/styles/treegrid/_material3-definition.scss +2 -0
- package/styles/treegrid/_tailwind-dark-definition.scss +26 -1
- package/styles/treegrid/_tailwind-definition.scss +2 -0
- package/styles/treegrid/_tailwind3-definition.scss +2 -0
- package/styles/treegrid/_theme-variables.scss +1 -0
- package/styles/treegrid/bds.scss +19 -19
- package/styles/treegrid/bootstrap-dark.scss +19 -19
- package/styles/treegrid/bootstrap.scss +19 -19
- package/styles/treegrid/bootstrap4.scss +19 -19
- package/styles/treegrid/bootstrap5-dark.scss +19 -19
- package/styles/treegrid/bootstrap5.3.css +81 -1
- package/styles/treegrid/bootstrap5.3.scss +19 -19
- package/styles/treegrid/bootstrap5.scss +19 -19
- package/styles/treegrid/fabric-dark.scss +19 -19
- package/styles/treegrid/fabric.scss +19 -19
- package/styles/treegrid/fluent-dark.scss +19 -19
- package/styles/treegrid/fluent.scss +19 -19
- package/styles/treegrid/fluent2.css +152 -4
- package/styles/treegrid/fluent2.scss +19 -19
- package/styles/treegrid/highcontrast-light.scss +19 -19
- package/styles/treegrid/highcontrast.scss +19 -19
- package/styles/treegrid/icons/_bds.scss +1 -0
- package/styles/treegrid/icons/_bootstrap-dark.scss +1 -0
- package/styles/treegrid/icons/_bootstrap.scss +1 -0
- package/styles/treegrid/icons/_bootstrap4.scss +1 -0
- package/styles/treegrid/icons/_bootstrap5-dark.scss +1 -1
- package/styles/treegrid/icons/_bootstrap5.3.scss +1 -0
- package/styles/treegrid/icons/_bootstrap5.scss +1 -0
- package/styles/treegrid/icons/_fabric-dark.scss +1 -0
- package/styles/treegrid/icons/_fabric.scss +1 -0
- package/styles/treegrid/icons/_fluent-dark.scss +1 -1
- package/styles/treegrid/icons/_fluent.scss +1 -0
- package/styles/treegrid/icons/_fluent2.scss +1 -0
- package/styles/treegrid/icons/_fusionnew.scss +1 -0
- package/styles/treegrid/icons/_highcontrast-light.scss +1 -0
- package/styles/treegrid/icons/_highcontrast.scss +1 -0
- package/styles/treegrid/icons/_material-dark.scss +1 -0
- package/styles/treegrid/icons/_material.scss +1 -0
- package/styles/treegrid/icons/_material3-dark.scss +1 -1
- package/styles/treegrid/icons/_material3.scss +1 -0
- package/styles/treegrid/icons/_tailwind-dark.scss +1 -0
- package/styles/treegrid/icons/_tailwind.scss +1 -0
- package/styles/treegrid/icons/_tailwind3.scss +1 -0
- package/styles/treegrid/material-dark.scss +19 -19
- package/styles/treegrid/material.scss +19 -19
- package/styles/treegrid/material3-dark.css +140 -1
- package/styles/treegrid/material3-dark.scss +19 -20
- package/styles/treegrid/material3.css +140 -1
- package/styles/treegrid/material3.scss +19 -20
- package/styles/treegrid/tailwind-dark.scss +19 -19
- package/styles/treegrid/tailwind.scss +19 -19
- package/styles/treegrid/tailwind3.css +119 -1
- package/styles/treegrid/tailwind3.scss +19 -19
|
@@ -70,6 +70,18 @@ class Column {
|
|
|
70
70
|
* @default null
|
|
71
71
|
*/
|
|
72
72
|
this.filter = {};
|
|
73
|
+
/**
|
|
74
|
+
* Allows treegrid to perform row spanning on the specified column.
|
|
75
|
+
*
|
|
76
|
+
* @default true
|
|
77
|
+
*/
|
|
78
|
+
this.enableRowSpan = true;
|
|
79
|
+
/**
|
|
80
|
+
* Allows treegrid to perform column spanning on the specified column.
|
|
81
|
+
*
|
|
82
|
+
* @default true
|
|
83
|
+
*/
|
|
84
|
+
this.enableColumnSpan = true;
|
|
73
85
|
merge(this, options);
|
|
74
86
|
}
|
|
75
87
|
/**
|
|
@@ -875,27 +887,56 @@ function isHidden(el) {
|
|
|
875
887
|
*/
|
|
876
888
|
class Selection {
|
|
877
889
|
/**
|
|
878
|
-
*
|
|
890
|
+
* Creates an instance of Selection.
|
|
879
891
|
*
|
|
880
|
-
* @param {TreeGrid} parent -
|
|
892
|
+
* @param {TreeGrid} parent - The TreeGrid instance this selection module is associated with.
|
|
881
893
|
*/
|
|
882
894
|
constructor(parent) {
|
|
895
|
+
this.headerCheckboxFrameEl = null;
|
|
896
|
+
this.checkboxColIndexCache = -2;
|
|
897
|
+
this.parentSelectionCounters = {};
|
|
898
|
+
this.selectedUidMap = new Map(); // Quick lookup for whether an item is selected
|
|
899
|
+
this.totalSelectableCount = 0;
|
|
900
|
+
this.headerSelectionState = 'uncheck';
|
|
901
|
+
this.checkedItemCount = 0;
|
|
902
|
+
this.visibleUidIndex = {};
|
|
883
903
|
this.parent = parent;
|
|
884
904
|
this.selectedItems = [];
|
|
885
|
-
this.selectedIndexes = [];
|
|
905
|
+
this.selectedIndexes = []; // Initialize here
|
|
886
906
|
this.filteredList = [];
|
|
887
907
|
this.searchingRecords = [];
|
|
888
908
|
this.addEventListener();
|
|
889
909
|
}
|
|
890
910
|
/**
|
|
891
|
-
*
|
|
911
|
+
* Gets the module name.
|
|
892
912
|
*
|
|
893
|
-
* @
|
|
894
|
-
* @returns {string} Returns Selection module name
|
|
913
|
+
* @returns {string} The name of the module ('selection').
|
|
895
914
|
*/
|
|
896
|
-
getModuleName() {
|
|
897
|
-
|
|
915
|
+
getModuleName() { return 'selection'; }
|
|
916
|
+
/**
|
|
917
|
+
* Builds a map from visible record uniqueID to its visible index.
|
|
918
|
+
* This map is crucial for finding the *current visible index* of a record.
|
|
919
|
+
*
|
|
920
|
+
* @returns {void}
|
|
921
|
+
*/
|
|
922
|
+
buildVisibleUidMap() {
|
|
923
|
+
this.visibleUidIndex = {};
|
|
924
|
+
const view = this.parent.grid.currentViewData;
|
|
925
|
+
if (!view) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
for (let i = 0, len = view.length; i < len; i++) {
|
|
929
|
+
const rec = view[parseInt(i.toString(), 10)];
|
|
930
|
+
if (rec && rec.uniqueID) {
|
|
931
|
+
this.visibleUidIndex[rec.uniqueID] = i; // Map uid -> visible row index
|
|
932
|
+
}
|
|
933
|
+
}
|
|
898
934
|
}
|
|
935
|
+
/**
|
|
936
|
+
* Adds required event listeners for selection handling.
|
|
937
|
+
*
|
|
938
|
+
* @returns {void}
|
|
939
|
+
*/
|
|
899
940
|
addEventListener() {
|
|
900
941
|
this.parent.on('dataBoundArg', this.headerCheckbox, this);
|
|
901
942
|
this.parent.on('columnCheckbox', this.columnCheckbox, this);
|
|
@@ -903,6 +944,11 @@ class Selection {
|
|
|
903
944
|
this.parent.grid.on('colgroup-refresh', this.headerCheckbox, this);
|
|
904
945
|
this.parent.on('checkboxSelection', this.checkboxSelection, this);
|
|
905
946
|
}
|
|
947
|
+
/**
|
|
948
|
+
* Removes previously added event listeners.
|
|
949
|
+
*
|
|
950
|
+
* @returns {void}
|
|
951
|
+
*/
|
|
906
952
|
removeEventListener() {
|
|
907
953
|
if (this.parent.isDestroyed) {
|
|
908
954
|
return;
|
|
@@ -914,14 +960,20 @@ class Selection {
|
|
|
914
960
|
this.parent.off('updateGridActions', this.updateGridActions);
|
|
915
961
|
}
|
|
916
962
|
/**
|
|
917
|
-
*
|
|
963
|
+
* Destroys the selection module and clears internal caches.
|
|
918
964
|
*
|
|
919
965
|
* @returns {void}
|
|
920
|
-
* @hidden
|
|
921
966
|
*/
|
|
922
967
|
destroy() {
|
|
968
|
+
this.resetSelectionCaches();
|
|
923
969
|
this.removeEventListener();
|
|
924
970
|
}
|
|
971
|
+
/**
|
|
972
|
+
* Handles checkbox click events from the DOM and dispatches selection logic.
|
|
973
|
+
*
|
|
974
|
+
* @param {Object} args - Event args containing the click target.
|
|
975
|
+
* @returns {void}
|
|
976
|
+
*/
|
|
925
977
|
checkboxSelection(args) {
|
|
926
978
|
const target = getObject('target', args);
|
|
927
979
|
const checkWrap = parentsUntil(target, 'e-checkbox-wrapper');
|
|
@@ -929,16 +981,23 @@ class Selection {
|
|
|
929
981
|
if (checkWrap && checkWrap.querySelectorAll('.e-treecheckselect').length > 0) {
|
|
930
982
|
checkBox = checkWrap.querySelector('input[type="checkbox"]');
|
|
931
983
|
const rowIndex = [];
|
|
932
|
-
|
|
984
|
+
if (this.parent.frozenRows) {
|
|
985
|
+
rowIndex.push(parseInt(target.closest('tr').getAttribute('aria-rowindex'), 10) - 1);
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
rowIndex.push(target.closest('tr').rowIndex);
|
|
989
|
+
}
|
|
933
990
|
this.selectCheckboxes(rowIndex);
|
|
934
|
-
|
|
991
|
+
const newCheckState = checkBox.nextElementSibling.classList.contains('e-check');
|
|
992
|
+
this.triggerChkChangeEvent(checkBox, newCheckState, target.closest('tr'));
|
|
935
993
|
}
|
|
936
994
|
else if (checkWrap && checkWrap.querySelectorAll('.e-treeselectall').length > 0 && this.parent.autoCheckHierarchy) {
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
995
|
+
const frame = checkWrap.querySelector('.e-frame');
|
|
996
|
+
const currentStateIsUncheck = !frame.classList.contains('e-check') && !frame.classList.contains('e-stop');
|
|
997
|
+
const targetState = currentStateIsUncheck; // If currently uncheck, target state is to check all.
|
|
998
|
+
this.headerSelection(targetState);
|
|
940
999
|
checkBox = checkWrap.querySelector('input[type="checkbox"]');
|
|
941
|
-
this.triggerChkChangeEvent(checkBox,
|
|
1000
|
+
this.triggerChkChangeEvent(checkBox, targetState, target.closest('tr'));
|
|
942
1001
|
}
|
|
943
1002
|
if (!isNullOrUndefined(this.parent['parentQuery']) && this.parent.selectionSettings.persistSelection
|
|
944
1003
|
&& this.parent['columnModel'].filter((col) => { return col.type === 'checkbox'; }).length > 0
|
|
@@ -949,63 +1008,99 @@ class Selection {
|
|
|
949
1008
|
}
|
|
950
1009
|
}
|
|
951
1010
|
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Triggers the checkboxChange event with the appropriate arguments.
|
|
1013
|
+
*
|
|
1014
|
+
* @param {HTMLInputElement} checkBox - The checkbox input element that changed.
|
|
1015
|
+
* @param {boolean} checkState - The new checked state.
|
|
1016
|
+
* @param {HTMLTableRowElement} rowElement - The row element where the change occurred.
|
|
1017
|
+
* @returns {void}
|
|
1018
|
+
*/
|
|
952
1019
|
triggerChkChangeEvent(checkBox, checkState, rowElement) {
|
|
953
1020
|
const data = this.parent.getCurrentViewRecords()[rowElement.rowIndex];
|
|
954
|
-
const args = {
|
|
1021
|
+
const args = {
|
|
1022
|
+
checked: checkState, target: checkBox, rowElement: rowElement,
|
|
955
1023
|
rowData: checkBox.classList.contains('e-treeselectall')
|
|
956
|
-
? this.parent.getCheckedRecords() : data
|
|
1024
|
+
? this.parent.getCheckedRecords() : data
|
|
1025
|
+
};
|
|
957
1026
|
this.parent.trigger(checkboxChange, args);
|
|
958
1027
|
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Determines the index of the checkbox column in the header.
|
|
1030
|
+
*
|
|
1031
|
+
* @returns {number} The index of the checkbox column, or -1 if not found.
|
|
1032
|
+
*/
|
|
959
1033
|
getCheckboxcolumnIndex() {
|
|
1034
|
+
if (this.checkboxColIndexCache !== -2) {
|
|
1035
|
+
return this.checkboxColIndexCache;
|
|
1036
|
+
}
|
|
960
1037
|
let mappingUid;
|
|
961
|
-
let columnIndex;
|
|
1038
|
+
let columnIndex = -1;
|
|
962
1039
|
const stackedHeader = 'stackedHeader';
|
|
963
1040
|
const columnModel = 'columnModel';
|
|
964
1041
|
const columns = this.parent[`${stackedHeader}`] ? this.parent[`${columnModel}`] : (this.parent.columns);
|
|
965
1042
|
for (let col = 0; col < columns.length; col++) {
|
|
966
1043
|
if (columns[parseInt(col.toString(), 10)].showCheckbox) {
|
|
967
1044
|
mappingUid = columns[parseInt(col.toString(), 10)].uid;
|
|
1045
|
+
break;
|
|
968
1046
|
}
|
|
969
1047
|
}
|
|
970
|
-
const
|
|
971
|
-
for (let j = 0; j <
|
|
972
|
-
const headercell =
|
|
1048
|
+
const headerDivs = this.parent.getHeaderContent().querySelectorAll('.e-headercelldiv');
|
|
1049
|
+
for (let j = 0; j < headerDivs.length; j++) {
|
|
1050
|
+
const headercell = headerDivs[parseInt(j.toString(), 10)];
|
|
973
1051
|
if (headercell.getAttribute('data-mappinguid') === mappingUid) {
|
|
974
1052
|
columnIndex = j;
|
|
1053
|
+
break;
|
|
975
1054
|
}
|
|
976
1055
|
}
|
|
977
|
-
|
|
1056
|
+
this.checkboxColIndexCache = isNullOrUndefined(columnIndex) ? -1 : columnIndex;
|
|
1057
|
+
return this.checkboxColIndexCache;
|
|
978
1058
|
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Renders and initializes the header checkbox element.
|
|
1061
|
+
*
|
|
1062
|
+
* @returns {void}
|
|
1063
|
+
*/
|
|
979
1064
|
headerCheckbox() {
|
|
1065
|
+
this.buildVisibleUidMap();
|
|
1066
|
+
this.totalSelectableCount = this.countSelectableRecords(this.resolveHeaderSelectionList(true)); // Use all flatData for initial count
|
|
980
1067
|
this.columnIndex = this.getCheckboxcolumnIndex();
|
|
981
|
-
if (this.columnIndex > -1
|
|
1068
|
+
if (this.columnIndex > -1) {
|
|
982
1069
|
const headerElement = this.parent.getHeaderContent().querySelectorAll('.e-headercelldiv')[this.columnIndex];
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
this.
|
|
1070
|
+
if (headerElement && headerElement.querySelectorAll('.e-treeselectall').length === 0) {
|
|
1071
|
+
const value = false; // Initial state can be false.
|
|
1072
|
+
const rowChkBox = this.parent.createElement('input', { className: 'e-treeselectall', attrs: { 'type': 'checkbox' } });
|
|
1073
|
+
const checkWrap = createCheckBox(this.parent.createElement, false, { checked: value, label: ' ' });
|
|
1074
|
+
checkWrap.classList.add('e-hierarchycheckbox');
|
|
1075
|
+
checkWrap.insertBefore(rowChkBox.cloneNode(), checkWrap.firstChild);
|
|
1076
|
+
if (!isNullOrUndefined(headerElement)) {
|
|
1077
|
+
headerElement.insertBefore(checkWrap, headerElement.firstChild);
|
|
1078
|
+
}
|
|
1079
|
+
this.headerCheckboxFrameEl = checkWrap.querySelector('.e-frame'); // Assign the frame element
|
|
1080
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1081
|
+
this.headerSelection();
|
|
1082
|
+
} // Update header state based on data
|
|
993
1083
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
this.headerSelection(checkBoxvalue);
|
|
1084
|
+
else if (headerElement && headerElement.querySelectorAll('.e-treeselectall').length > 0) {
|
|
1085
|
+
this.headerCheckboxFrameEl = headerElement.querySelector('.e-frame');
|
|
1086
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1087
|
+
this.headerSelection();
|
|
1088
|
+
} // Update status based on current selections
|
|
1000
1089
|
}
|
|
1001
1090
|
}
|
|
1002
1091
|
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Renders a checkbox element for a column cell.
|
|
1094
|
+
*
|
|
1095
|
+
* @param {QueryCellInfoEventArgs} args - The QueryCellInfoEventArgs for the cell.
|
|
1096
|
+
* @returns {Element} The rendered checkbox wrapper element.
|
|
1097
|
+
*/
|
|
1003
1098
|
renderColumnCheckbox(args) {
|
|
1004
1099
|
const rowChkBox = this.parent.createElement('input', { className: 'e-treecheckselect', attrs: { 'type': 'checkbox', 'aria-label': 'checkbox' } });
|
|
1005
1100
|
const data = args.data;
|
|
1006
1101
|
args.cell.classList.add('e-treegridcheckbox');
|
|
1007
1102
|
args.cell.setAttribute('aria-label', 'checkbox');
|
|
1008
|
-
const value = (
|
|
1103
|
+
const value = (data.checkboxState === 'check');
|
|
1009
1104
|
const checkWrap = createCheckBox(this.parent.createElement, false, { checked: value, label: ' ' });
|
|
1010
1105
|
checkWrap.classList.add('e-hierarchycheckbox');
|
|
1011
1106
|
if (this.parent.allowTextWrap) {
|
|
@@ -1016,9 +1111,25 @@ class Selection {
|
|
|
1016
1111
|
removeClass([checkbox], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1017
1112
|
checkWrap.querySelector('.e-frame').classList.add('e-stop');
|
|
1018
1113
|
}
|
|
1114
|
+
else if (data.checkboxState === 'uncheck') {
|
|
1115
|
+
const checkbox = checkWrap.querySelectorAll('.e-frame')[0];
|
|
1116
|
+
removeClass([checkbox], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1117
|
+
checkWrap.querySelector('.e-frame').classList.add('e-uncheck');
|
|
1118
|
+
}
|
|
1119
|
+
else if (data.checkboxState === 'check') {
|
|
1120
|
+
const checkbox = checkWrap.querySelectorAll('.e-frame')[0];
|
|
1121
|
+
removeClass([checkbox], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1122
|
+
checkWrap.querySelector('.e-frame').classList.add('e-check');
|
|
1123
|
+
}
|
|
1019
1124
|
checkWrap.insertBefore(rowChkBox.cloneNode(), checkWrap.firstChild);
|
|
1020
1125
|
return checkWrap;
|
|
1021
1126
|
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Injects the checkbox into a column cell during QueryCellInfo.
|
|
1129
|
+
*
|
|
1130
|
+
* @param {QueryCellInfoEventArgs} container - The cell event args.
|
|
1131
|
+
* @returns {void}
|
|
1132
|
+
*/
|
|
1022
1133
|
columnCheckbox(container) {
|
|
1023
1134
|
const checkWrap = this.renderColumnCheckbox(container);
|
|
1024
1135
|
const containerELe = container.cell.querySelector('.e-treecolumn-container');
|
|
@@ -1038,112 +1149,247 @@ class Selection {
|
|
|
1038
1149
|
container.cell.appendChild(divEle);
|
|
1039
1150
|
}
|
|
1040
1151
|
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Selects or toggles checkboxes for the provided row indexes.
|
|
1154
|
+
*
|
|
1155
|
+
* @param {number[]} rowIndexes - Array of row indexes to toggle selection for.
|
|
1156
|
+
* @returns {void}
|
|
1157
|
+
*/
|
|
1041
1158
|
selectCheckboxes(rowIndexes) {
|
|
1042
|
-
if (isNullOrUndefined(rowIndexes)) {
|
|
1043
|
-
const error = 'The provided value for the rowIndexes is undefined. Please ensure the rowIndexes contains number.';
|
|
1044
|
-
this.parent.trigger(actionFailure, { error: error });
|
|
1045
|
-
}
|
|
1046
1159
|
for (let i = 0; i < rowIndexes.length; i++) {
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
const keys = Object.keys(record);
|
|
1053
|
-
for (let j = 0; j < keys.length; j++) {
|
|
1054
|
-
if (Object.prototype.hasOwnProperty.call(flatRecord, keys[parseInt(j.toString(), 10)])) {
|
|
1055
|
-
flatRecord[keys[parseInt(j.toString(), 10)]] = record[keys[parseInt(j.toString(), 10)]];
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
this.traverSelection(record, checkboxState, false);
|
|
1059
|
-
if (this.parent.autoCheckHierarchy) {
|
|
1060
|
-
this.headerSelection();
|
|
1061
|
-
}
|
|
1160
|
+
const viewRec = this.parent.getCurrentViewRecords()[rowIndexes[parseInt(i.toString(), 10)]];
|
|
1161
|
+
const flatRec = getParentData(this.parent, viewRec.uniqueID);
|
|
1162
|
+
const nextState = (flatRec.checkboxState === 'check') ? 'uncheck' : 'check';
|
|
1163
|
+
flatRec.checkboxState = nextState;
|
|
1164
|
+
this.traverSelection(flatRec, nextState, false);
|
|
1062
1165
|
}
|
|
1063
1166
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1167
|
+
/**
|
|
1168
|
+
* Traverses selection for a record and cascades selections to children/parents as necessary.
|
|
1169
|
+
*
|
|
1170
|
+
* @param {ITreeData} record - The record to process.
|
|
1171
|
+
* @param {string} checkboxState - The desired checkbox state ('check'|'uncheck'|'indeterminate').
|
|
1172
|
+
* @param {boolean} isChildItem - True if this invocation is for a child during recursion.
|
|
1173
|
+
* @returns {void}
|
|
1174
|
+
*/
|
|
1175
|
+
traverSelection(record, checkboxState, isChildItem) {
|
|
1176
|
+
const previousState = record.checkboxState;
|
|
1177
|
+
if (!isChildItem) {
|
|
1178
|
+
this.buildVisibleUidMap();
|
|
1179
|
+
}
|
|
1180
|
+
let effectiveChildren = Array.isArray(record.childRecords) ? record.childRecords : [];
|
|
1181
|
+
if ((!effectiveChildren || effectiveChildren.length === 0) && this.parent.autoCheckHierarchy) {
|
|
1182
|
+
effectiveChildren = this.getChildrenFromFlat(record);
|
|
1183
|
+
}
|
|
1184
|
+
if (this.parent.filterModule && this.parent.filterModule.filteredResult.length > 0
|
|
1185
|
+
&& effectiveChildren && effectiveChildren.length) {
|
|
1186
|
+
effectiveChildren = this.getFilteredChildRecords(effectiveChildren);
|
|
1187
|
+
}
|
|
1188
|
+
if (!this.parent.autoCheckHierarchy || !effectiveChildren || effectiveChildren.length === 0) {
|
|
1189
|
+
this.updateSelectedItems(record, checkboxState);
|
|
1190
|
+
if (!isChildItem) {
|
|
1191
|
+
if (record.parentItem && this.parent.autoCheckHierarchy) {
|
|
1192
|
+
this.updateParentSelection(record.parentItem);
|
|
1193
|
+
}
|
|
1194
|
+
this.updateSelectedCollectionsAfterBulk(this.resolveHeaderSelectionList(), '');
|
|
1195
|
+
this.refreshVisibleCheckboxes();
|
|
1196
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1197
|
+
this.updateHeaderCheckboxState();
|
|
1085
1198
|
}
|
|
1086
1199
|
}
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
let childCount = 0;
|
|
1203
|
+
let checkedCount = 0;
|
|
1204
|
+
let indeterminateCount = 0;
|
|
1205
|
+
for (let i = 0; i < effectiveChildren.length; i++) {
|
|
1206
|
+
const child = effectiveChildren[parseInt(i.toString(), 10)];
|
|
1207
|
+
if (!child || child.isSummaryRow) {
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
childCount++;
|
|
1211
|
+
this.updateSelectedItems(child, checkboxState, true);
|
|
1212
|
+
if (child.hasChildRecords) {
|
|
1213
|
+
this.traverSelection(child, checkboxState, true);
|
|
1214
|
+
}
|
|
1215
|
+
if (child.checkboxState === 'check') {
|
|
1216
|
+
checkedCount++;
|
|
1217
|
+
}
|
|
1218
|
+
else if (child.checkboxState === 'indeterminate') {
|
|
1219
|
+
indeterminateCount++;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
if (record.uniqueID) {
|
|
1223
|
+
this.parentSelectionCounters[record.uniqueID] = {
|
|
1224
|
+
total: childCount,
|
|
1225
|
+
checked: checkedCount,
|
|
1226
|
+
indeterminate: indeterminateCount
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
const summary = this.parentSelectionCounters[record.uniqueID];
|
|
1230
|
+
let finalState = this.deriveParentState(record, summary);
|
|
1231
|
+
if (checkboxState === 'check' && summary.total > 0 && summary.checked === summary.total && summary.indeterminate === 0) {
|
|
1232
|
+
finalState = 'check';
|
|
1233
|
+
}
|
|
1234
|
+
this.updateSelectedItems(record, finalState);
|
|
1235
|
+
if (!isChildItem && record.parentItem && this.parent.autoCheckHierarchy) {
|
|
1236
|
+
this.updateParentSelection(record.parentItem, previousState, finalState);
|
|
1237
|
+
}
|
|
1238
|
+
if (!isChildItem) {
|
|
1239
|
+
const bulkList = this.resolveHeaderSelectionList();
|
|
1240
|
+
this.updateSelectedCollectionsAfterBulk(bulkList, ''); // This will rebuild selectedItems & selectedIndexes based on total state
|
|
1241
|
+
this.refreshVisibleCheckboxes();
|
|
1242
|
+
this.updateHeaderCheckboxState();
|
|
1087
1243
|
}
|
|
1088
1244
|
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Filters provided child records against the current filter result.
|
|
1247
|
+
*
|
|
1248
|
+
* @param {ITreeData[]} childRecords - The array of child records to filter.
|
|
1249
|
+
* @returns {ITreeData[]} The filtered child records array.
|
|
1250
|
+
*/
|
|
1089
1251
|
getFilteredChildRecords(childRecords) {
|
|
1090
1252
|
const filteredChildRecords = childRecords.filter((e) => {
|
|
1091
1253
|
return this.parent.filterModule.filteredResult.indexOf(e) > -1;
|
|
1092
1254
|
});
|
|
1093
1255
|
return filteredChildRecords;
|
|
1094
1256
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
if (!isNullOrUndefined(checkBoxRecord)) {
|
|
1114
|
-
if (checkBoxRecord.checkboxState === 'indeterminate') {
|
|
1115
|
-
indeter++;
|
|
1116
|
-
}
|
|
1117
|
-
else if (checkBoxRecord.checkboxState === 'check') {
|
|
1118
|
-
checkChildRecords++;
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
if (indeter > 0 || (checkChildRecords > 0 && checkChildRecords !== length)) {
|
|
1123
|
-
record.checkboxState = 'indeterminate';
|
|
1257
|
+
/**
|
|
1258
|
+
* Derives children for a record from flatData using the parentItem link.
|
|
1259
|
+
* Used when childRecords is missing or empty.
|
|
1260
|
+
*
|
|
1261
|
+
* @param {ITreeData} record - The record for which to find child elements.
|
|
1262
|
+
* @returns {ITreeData[]} An array of child records derived from flatData.
|
|
1263
|
+
*/
|
|
1264
|
+
getChildrenFromFlat(record) {
|
|
1265
|
+
const all = (this.parent.flatData);
|
|
1266
|
+
if (!all || !record) {
|
|
1267
|
+
return [];
|
|
1268
|
+
}
|
|
1269
|
+
const pid = record.uniqueID;
|
|
1270
|
+
const out = [];
|
|
1271
|
+
for (let i = 0; i < all.length; i++) {
|
|
1272
|
+
const r = all[parseInt(i.toString(), 10)];
|
|
1273
|
+
if (!r || r.isSummaryRow) {
|
|
1274
|
+
continue;
|
|
1124
1275
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1276
|
+
const p = r.parentItem;
|
|
1277
|
+
if (p && p.uniqueID === pid) {
|
|
1278
|
+
out.push(r);
|
|
1128
1279
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1280
|
+
}
|
|
1281
|
+
return out;
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Updates parent selection by rebuilding summary and applying deltas, then bubbling up if required.
|
|
1285
|
+
*
|
|
1286
|
+
* @param {ITreeData} parentRecord - The parent record reference.
|
|
1287
|
+
* @param {string} [previousChildState] - Previous state of the child that changed.
|
|
1288
|
+
* @param {string} [nextChildState] - Next state of the child that changed.
|
|
1289
|
+
* @returns {void}
|
|
1290
|
+
*/
|
|
1291
|
+
updateParentSelection(parentRecord, previousChildState, nextChildState) {
|
|
1292
|
+
const parent = getParentData(this.parent, parentRecord.uniqueID);
|
|
1293
|
+
if (!parent) {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
const summary = this.buildSelectionSummary(parent);
|
|
1297
|
+
if (previousChildState) {
|
|
1298
|
+
this.applySummaryDelta(summary, previousChildState, -1);
|
|
1299
|
+
}
|
|
1300
|
+
if (nextChildState) {
|
|
1301
|
+
this.applySummaryDelta(summary, nextChildState, 1);
|
|
1302
|
+
}
|
|
1303
|
+
if (parent.uniqueID) {
|
|
1304
|
+
this.parentSelectionCounters[parent.uniqueID] = summary;
|
|
1305
|
+
}
|
|
1306
|
+
const desiredState = this.deriveParentState(parent, summary);
|
|
1307
|
+
if (parent.checkboxState === desiredState) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
const parentPrev = parent.checkboxState;
|
|
1311
|
+
parent.checkboxState = desiredState;
|
|
1312
|
+
this.updateSelectedItems(parent, desiredState);
|
|
1313
|
+
if (parent.parentItem) {
|
|
1314
|
+
this.updateParentSelection(parent.parentItem, parentPrev, desiredState);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Builds a selection summary for a record's children.
|
|
1319
|
+
*
|
|
1320
|
+
* @param {Object} record - The record whose children should be summarized.
|
|
1321
|
+
* @param {boolean} [ignoreFilter] - If true, ignore current filter when computing summary.
|
|
1322
|
+
* @returns {{ total: number, checked: number, indeterminate: number }} The computed summary.
|
|
1323
|
+
*/
|
|
1324
|
+
buildSelectionSummary(record, ignoreFilter) {
|
|
1325
|
+
const summary = { total: 0, checked: 0, indeterminate: 0 };
|
|
1326
|
+
let children = [];
|
|
1327
|
+
if (record && Array.isArray(record.childRecords) && record.childRecords.length) {
|
|
1328
|
+
children = record.childRecords;
|
|
1329
|
+
}
|
|
1330
|
+
else {
|
|
1331
|
+
children = this.getChildrenFromFlat(record);
|
|
1332
|
+
}
|
|
1333
|
+
if (!ignoreFilter && this.parent.filterModule && this.parent.filterModule.filteredResult.length > 0) {
|
|
1334
|
+
children = this.getFilteredChildRecords(children);
|
|
1335
|
+
}
|
|
1336
|
+
for (let i = 0; i < children.length; i++) {
|
|
1337
|
+
const child = children[parseInt(i.toString(), 10)];
|
|
1338
|
+
if (!child || child.isSummaryRow) {
|
|
1339
|
+
continue;
|
|
1132
1340
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1341
|
+
summary.total++;
|
|
1342
|
+
if (child.checkboxState === 'check') {
|
|
1343
|
+
summary.checked++;
|
|
1135
1344
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
this.updateParentSelection(record.parentItem);
|
|
1345
|
+
else if (child.checkboxState === 'indeterminate') {
|
|
1346
|
+
summary.indeterminate++;
|
|
1139
1347
|
}
|
|
1140
1348
|
}
|
|
1349
|
+
return summary;
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Applies a delta to a selection summary based on a state change.
|
|
1353
|
+
*
|
|
1354
|
+
* @param {Object} summary - The summary to modify. Object with numeric properties: total, checked, indeterminate.
|
|
1355
|
+
* @param {string} state - The state that changed ('check' | 'indeterminate').
|
|
1356
|
+
* @param {number} delta - The delta to apply (e.g. +1 or -1).
|
|
1357
|
+
* @returns {void}
|
|
1358
|
+
*/
|
|
1359
|
+
applySummaryDelta(summary, state, delta) {
|
|
1360
|
+
if (state === 'check') {
|
|
1361
|
+
summary.checked = Math.max(0, summary.checked + delta);
|
|
1362
|
+
}
|
|
1363
|
+
else if (state === 'indeterminate') {
|
|
1364
|
+
summary.indeterminate = Math.max(0, summary.indeterminate + delta);
|
|
1365
|
+
}
|
|
1141
1366
|
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Derives the parent's checkbox state based on children summary counts.
|
|
1369
|
+
*
|
|
1370
|
+
* @param {ITreeData} record The parent record.
|
|
1371
|
+
* @param {{ total: number, checked: number, indeterminate: number }} summary The children summary.
|
|
1372
|
+
* @returns {'check'|'indeterminate'|'uncheck'} The derived checkbox state.
|
|
1373
|
+
*/
|
|
1374
|
+
deriveParentState(record, summary) {
|
|
1375
|
+
const total = summary.total;
|
|
1376
|
+
const checked = summary.checked;
|
|
1377
|
+
const indeterminate = summary.indeterminate;
|
|
1378
|
+
if (indeterminate > 0 || (checked > 0 && checked !== total)) {
|
|
1379
|
+
return 'indeterminate';
|
|
1380
|
+
}
|
|
1381
|
+
if (checked === total && total > 0) {
|
|
1382
|
+
return 'check';
|
|
1383
|
+
}
|
|
1384
|
+
return 'uncheck';
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Handles header checkbox (select all / clear all) behavior.
|
|
1388
|
+
*
|
|
1389
|
+
* @param {boolean} [checkAll] - Optional explicit flag to check or uncheck all.
|
|
1390
|
+
* @returns {void}
|
|
1391
|
+
*/
|
|
1142
1392
|
headerSelection(checkAll) {
|
|
1143
|
-
let index = -1;
|
|
1144
|
-
let length = 0;
|
|
1145
|
-
//This property used to maintain the check state of the currentview data after clear filtering
|
|
1146
|
-
let multiFilterCheckState = false;
|
|
1147
1393
|
if (!isNullOrUndefined(this.parent.filterModule) && this.parent.filterModule.filteredResult.length > 0) {
|
|
1148
1394
|
const filterResult = this.parent.filterModule.filteredResult;
|
|
1149
1395
|
if (this.filteredList.length === 0) {
|
|
@@ -1153,160 +1399,397 @@ class Selection {
|
|
|
1153
1399
|
this.searchingRecords = filterResult;
|
|
1154
1400
|
}
|
|
1155
1401
|
else {
|
|
1156
|
-
if (this.filteredList !== filterResult) {
|
|
1402
|
+
if (this.filteredList !== filterResult && !this.parent.grid.searchSettings.key.length) {
|
|
1157
1403
|
this.filteredList = filterResult;
|
|
1158
|
-
|
|
1159
|
-
}
|
|
1160
|
-
else {
|
|
1161
|
-
multiFilterCheckState = false;
|
|
1404
|
+
this.searchingRecords = [];
|
|
1162
1405
|
}
|
|
1163
1406
|
}
|
|
1164
1407
|
}
|
|
1165
|
-
if (this.
|
|
1166
|
-
|
|
1167
|
-
|
|
1408
|
+
if (this.searchingRecords.length > 0 && !isNullOrUndefined(checkAll)) {
|
|
1409
|
+
this.filteredList = this.searchingRecords;
|
|
1410
|
+
}
|
|
1411
|
+
else if (this.filteredList.length > 0 && !this.parent.filterSettings.columns.length
|
|
1412
|
+
&& !this.parent.grid.searchSettings.key.length) {
|
|
1413
|
+
this.filteredList = [];
|
|
1414
|
+
}
|
|
1415
|
+
const records = this.resolveHeaderSelectionList(true);
|
|
1416
|
+
if (!isNullOrUndefined(checkAll)) {
|
|
1417
|
+
this.resetSelectionCaches();
|
|
1418
|
+
const targetState = checkAll ? 'check' : 'uncheck';
|
|
1419
|
+
this.headerSelectionState = targetState;
|
|
1420
|
+
this.processHeaderSelection(records, targetState);
|
|
1421
|
+
this.finalizeParentsAfterBulk(records);
|
|
1422
|
+
this.updateSelectedCollectionsAfterBulk(records, '');
|
|
1423
|
+
this.refreshVisibleCheckboxes();
|
|
1424
|
+
this.updateHeaderCheckboxState();
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
this.totalSelectableCount = this.countSelectableRecords(records);
|
|
1428
|
+
this.updateHeaderCheckboxState();
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Finalizes parent states after a bulk header operation (e.g., Select All).
|
|
1432
|
+
* This ensures parent states (checked/indeterminate) are correct after cascades.
|
|
1433
|
+
*
|
|
1434
|
+
* @param {ITreeData[]} records - The records that were processed in the bulk operation.
|
|
1435
|
+
* @returns {void}
|
|
1436
|
+
*/
|
|
1437
|
+
finalizeParentsAfterBulk(records) {
|
|
1438
|
+
const all = records;
|
|
1439
|
+
for (let i = 0; i < all.length; i++) {
|
|
1440
|
+
const rec = all[parseInt(i.toString(), 10)];
|
|
1441
|
+
if (!rec || !rec.hasChildRecords) {
|
|
1442
|
+
continue;
|
|
1168
1443
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1444
|
+
const summary = this.buildSelectionSummary(rec, true);
|
|
1445
|
+
this.parentSelectionCounters[rec.uniqueID] = summary;
|
|
1446
|
+
let finalState = this.deriveParentState(rec, summary);
|
|
1447
|
+
if (this.headerSelectionState === 'check' &&
|
|
1448
|
+
summary.total > 0 && summary.checked === summary.total && summary.indeterminate === 0) {
|
|
1449
|
+
finalState = 'check';
|
|
1450
|
+
}
|
|
1451
|
+
else if (this.headerSelectionState === 'uncheck') {
|
|
1452
|
+
finalState = 'uncheck';
|
|
1453
|
+
}
|
|
1454
|
+
if (rec.checkboxState !== finalState) {
|
|
1455
|
+
this.updateSelectedItems(rec, finalState);
|
|
1171
1456
|
}
|
|
1172
1457
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Processes header selection for each record, setting their state silently in the data model.
|
|
1461
|
+
* Called during bulk operations like "select all".
|
|
1462
|
+
*
|
|
1463
|
+
* @param {ITreeData[]} records - The records to process.
|
|
1464
|
+
* @param {string} targetState - The target state to set on each record.
|
|
1465
|
+
* @returns {void}
|
|
1466
|
+
*/
|
|
1467
|
+
processHeaderSelection(records, targetState) {
|
|
1468
|
+
for (let i = 0; i < records.length; i++) {
|
|
1469
|
+
const record = records[parseInt(i.toString(), 10)];
|
|
1470
|
+
if (!record) {
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
const previousState = record.checkboxState;
|
|
1474
|
+
if (previousState === targetState) {
|
|
1475
|
+
continue;
|
|
1476
|
+
}
|
|
1477
|
+
record.checkboxState = targetState;
|
|
1478
|
+
this.updateSelectedItems(record, targetState, true);
|
|
1182
1479
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Rebuilds `selectedItems`, `selectedUidMap`, and `selectedIndexes` based on the current data states in the model.
|
|
1483
|
+
* This method is called after bulk operations (like headerSelection, grid actions, etc.) to synchronize internal collections.
|
|
1484
|
+
* It ensures `selectedItems` retains original selection order *as much as possible* for currently checked items
|
|
1485
|
+
* and `selectedIndexes` reflects their *current visible order*.
|
|
1486
|
+
*
|
|
1487
|
+
* @param {ITreeData[]} records - The records that were processed (or the full data set if re-evaluating everything).
|
|
1488
|
+
* @param {string} requestType - The data action type such as filtering, searching, refresh,etc.
|
|
1489
|
+
* @returns {void}
|
|
1490
|
+
*/
|
|
1491
|
+
updateSelectedCollectionsAfterBulk(records, requestType) {
|
|
1492
|
+
const hasFilter = !!(this.parent.filterModule && this.parent.filterModule.filteredResult &&
|
|
1493
|
+
this.parent.filterModule.filteredResult.length);
|
|
1494
|
+
const hasSearch = !!(this.parent.grid && this.parent.grid.searchSettings &&
|
|
1495
|
+
this.parent.grid.searchSettings.key && this.parent.grid.searchSettings.key.length);
|
|
1496
|
+
const isFilterOrSearch = hasFilter || hasSearch || requestType === 'refresh' || requestType === 'searching';
|
|
1497
|
+
const currentlySelectedItemsInOrder = isFilterOrSearch ? records : this.selectedItems.slice();
|
|
1498
|
+
const newSelectedItems = [];
|
|
1499
|
+
const newSelectedUidMap = new Map();
|
|
1500
|
+
const newSelectedIndexes = [];
|
|
1501
|
+
for (const item of currentlySelectedItemsInOrder) {
|
|
1502
|
+
if (item.hasChildRecords && isFilterOrSearch && item.level === 0) {
|
|
1503
|
+
this.updateParentSelection(item);
|
|
1504
|
+
}
|
|
1505
|
+
if (item.uniqueID && item.checkboxState === 'check') {
|
|
1506
|
+
newSelectedItems.push(item);
|
|
1507
|
+
newSelectedUidMap.set(item.uniqueID, true);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
if (!isFilterOrSearch) {
|
|
1511
|
+
const allFlatData = this.parent.flatData;
|
|
1512
|
+
if (allFlatData) {
|
|
1513
|
+
for (const record of allFlatData) {
|
|
1514
|
+
if (!record || record.isSummaryRow) {
|
|
1188
1515
|
continue;
|
|
1189
1516
|
}
|
|
1190
|
-
if (
|
|
1191
|
-
|
|
1517
|
+
if (record.uniqueID && record.checkboxState === 'check' && !newSelectedUidMap.has(record.uniqueID)) {
|
|
1518
|
+
newSelectedItems.push(record);
|
|
1519
|
+
newSelectedUidMap.set(record.uniqueID, true);
|
|
1192
1520
|
}
|
|
1193
|
-
data[parseInt(i.toString(), 10)].checkboxState = 'check';
|
|
1194
|
-
this.updateSelectedItems(data[parseInt(i.toString(), 10)], data[parseInt(i.toString(), 10)].checkboxState);
|
|
1195
1521
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
this.selectedItems = newSelectedItems;
|
|
1525
|
+
this.selectedUidMap = newSelectedUidMap;
|
|
1526
|
+
this.buildVisibleUidMap();
|
|
1527
|
+
for (const item of this.selectedItems) {
|
|
1528
|
+
const visibleIdx = this.visibleUidIndex[item.uniqueID];
|
|
1529
|
+
if (visibleIdx !== undefined) {
|
|
1530
|
+
newSelectedIndexes.push(visibleIdx);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
this.selectedIndexes = newSelectedIndexes;
|
|
1534
|
+
this.checkedItemCount = this.selectedItems.length;
|
|
1535
|
+
this.totalSelectableCount =
|
|
1536
|
+
this.countSelectableRecords(records);
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Refreshes visible checkbox DOM elements to reflect the current data state.
|
|
1540
|
+
* This method exclusively updates the UI representation of checkboxes.
|
|
1541
|
+
*
|
|
1542
|
+
* @returns {void}
|
|
1543
|
+
*/
|
|
1544
|
+
refreshVisibleCheckboxes() {
|
|
1545
|
+
this.buildVisibleUidMap();
|
|
1546
|
+
const data = this.parent.getCurrentViewRecords();
|
|
1547
|
+
const uidMap = this.parent.uniqueIDCollection;
|
|
1548
|
+
for (let i = 0; data && i < data.length; i++) {
|
|
1549
|
+
const viewRec = data[parseInt(i.toString(), 10)];
|
|
1550
|
+
if (!viewRec) {
|
|
1551
|
+
continue;
|
|
1552
|
+
}
|
|
1553
|
+
const uid = viewRec.uniqueID;
|
|
1554
|
+
const srcRec = (uidMap && uid != null) ? uidMap[String(uid)] : viewRec;
|
|
1555
|
+
const state = (srcRec && srcRec.checkboxState) ? srcRec.checkboxState : 'uncheck';
|
|
1556
|
+
let rowEl = null;
|
|
1557
|
+
const rowUid = viewRec.uid;
|
|
1558
|
+
if (rowUid) {
|
|
1559
|
+
rowEl = this.parent.grid.getRowElementByUID(rowUid);
|
|
1560
|
+
}
|
|
1561
|
+
if (!rowEl) {
|
|
1562
|
+
const rows = this.parent.getRows();
|
|
1563
|
+
rowEl = rows && rows[parseInt(i.toString(), 10)];
|
|
1564
|
+
if ((this.parent.frozenRows || this.parent.getFrozenColumns()) && !rowEl) {
|
|
1565
|
+
const movableRows = this.parent.getDataRows();
|
|
1566
|
+
rowEl = movableRows && movableRows[parseInt(i.toString(), 10)];
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
if (rowEl) {
|
|
1570
|
+
const frame = rowEl.querySelector('.e-hierarchycheckbox .e-frame');
|
|
1571
|
+
if (frame) {
|
|
1572
|
+
removeClass([frame], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1573
|
+
frame.classList.add(state === 'indeterminate' ? 'e-stop' : ('e-' + state));
|
|
1574
|
+
const input = rowEl.querySelector('.e-treecheckselect');
|
|
1575
|
+
if (input) {
|
|
1576
|
+
input.setAttribute('aria-checked', state === 'check' ? 'true' :
|
|
1577
|
+
(state === 'uncheck' ? 'false' : 'mixed'));
|
|
1204
1578
|
}
|
|
1205
1579
|
}
|
|
1206
1580
|
}
|
|
1207
1581
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1582
|
+
}
|
|
1583
|
+
/**
|
|
1584
|
+
* Resets internal selection caches to their initial state.
|
|
1585
|
+
* This is usually called before a bulk selection operation (like "select all").
|
|
1586
|
+
*
|
|
1587
|
+
* @returns {void}
|
|
1588
|
+
*/
|
|
1589
|
+
resetSelectionCaches() {
|
|
1590
|
+
this.parentSelectionCounters = {};
|
|
1591
|
+
this.selectedUidMap = new Map();
|
|
1592
|
+
this.selectedItems = [];
|
|
1593
|
+
this.selectedIndexes = [];
|
|
1594
|
+
this.totalSelectableCount = 0;
|
|
1595
|
+
this.headerSelectionState = 'uncheck';
|
|
1596
|
+
this.checkedItemCount = 0;
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Counts selectable (non-summary) records in the provided array.
|
|
1600
|
+
*
|
|
1601
|
+
* @param {ITreeData[]} records - The records to count.
|
|
1602
|
+
* @returns {number} The number of selectable records.
|
|
1603
|
+
*/
|
|
1604
|
+
countSelectableRecords(records) {
|
|
1605
|
+
let count = 0;
|
|
1606
|
+
if (!records) {
|
|
1607
|
+
return count;
|
|
1215
1608
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1609
|
+
for (let i = 0; i < records.length; i++) {
|
|
1610
|
+
const rec = records[parseInt(i.toString(), 10)];
|
|
1611
|
+
if (rec && !rec.isSummaryRow) {
|
|
1612
|
+
count++;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return count;
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Resolves the list of records used for header selection operations (e.g., for `select all`).
|
|
1619
|
+
*
|
|
1620
|
+
* @param {boolean} [includeAll] - If true and data is local, returns flatData (all records for full dataset actions).
|
|
1621
|
+
* @returns {ITreeData[]} The array of records to consider for header operations.
|
|
1622
|
+
*/
|
|
1623
|
+
resolveHeaderSelectionList(includeAll) {
|
|
1624
|
+
let dataToProcess = [];
|
|
1625
|
+
if (!isRemoteData(this.parent)) {
|
|
1626
|
+
const hasFilter = !!(this.parent.filterModule &&
|
|
1627
|
+
this.parent.filterModule.filteredResult &&
|
|
1628
|
+
this.parent.filterModule.filteredResult.length);
|
|
1629
|
+
const hasSearch = !!(this.parent.grid &&
|
|
1630
|
+
this.parent.grid.searchSettings &&
|
|
1631
|
+
this.parent.grid.searchSettings.key &&
|
|
1632
|
+
this.parent.grid.searchSettings.key.length);
|
|
1633
|
+
if (includeAll) {
|
|
1634
|
+
if (hasFilter) {
|
|
1635
|
+
dataToProcess = this.filteredList && this.filteredList.length
|
|
1636
|
+
? this.filteredList
|
|
1637
|
+
: this.parent.filterModule.filteredResult;
|
|
1638
|
+
}
|
|
1639
|
+
else if (hasSearch && this.searchingRecords && this.searchingRecords.length) {
|
|
1640
|
+
dataToProcess = this.searchingRecords;
|
|
1641
|
+
}
|
|
1642
|
+
else {
|
|
1643
|
+
dataToProcess = this.parent.flatData;
|
|
1644
|
+
}
|
|
1222
1645
|
}
|
|
1223
1646
|
else {
|
|
1224
|
-
|
|
1225
|
-
|
|
1647
|
+
if (hasFilter) {
|
|
1648
|
+
dataToProcess = this.filteredList && this.filteredList.length
|
|
1649
|
+
? this.filteredList
|
|
1650
|
+
: this.parent.filterModule.filteredResult;
|
|
1651
|
+
}
|
|
1652
|
+
else if (hasSearch && this.searchingRecords && this.searchingRecords.length) {
|
|
1653
|
+
dataToProcess = this.searchingRecords;
|
|
1654
|
+
}
|
|
1655
|
+
else {
|
|
1656
|
+
dataToProcess = this.parent.flatData;
|
|
1657
|
+
}
|
|
1226
1658
|
}
|
|
1227
1659
|
}
|
|
1228
1660
|
else {
|
|
1229
|
-
|
|
1661
|
+
dataToProcess = this.parent.getCurrentViewRecords();
|
|
1230
1662
|
}
|
|
1663
|
+
return dataToProcess;
|
|
1231
1664
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
if (!isNullOrUndefined(checkbox)) {
|
|
1249
|
-
removeClass([checkbox], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1665
|
+
/**
|
|
1666
|
+
* Updates the header checkbox state (checked/indeterminate/unchecked) based on current selections.
|
|
1667
|
+
*
|
|
1668
|
+
* @returns {void}
|
|
1669
|
+
*/
|
|
1670
|
+
updateHeaderCheckboxState() {
|
|
1671
|
+
const frame = this.headerCheckboxFrameEl;
|
|
1672
|
+
if (!frame) {
|
|
1673
|
+
return;
|
|
1674
|
+
}
|
|
1675
|
+
const recordsForHeaderLogic = this.resolveHeaderSelectionList(true);
|
|
1676
|
+
this.totalSelectableCount = this.countSelectableRecords(recordsForHeaderLogic);
|
|
1677
|
+
let checkedCountForHeaderLogic = 0;
|
|
1678
|
+
for (const record of recordsForHeaderLogic) {
|
|
1679
|
+
if (record && !record.isSummaryRow && record.checkboxState === 'check') {
|
|
1680
|
+
checkedCountForHeaderLogic++;
|
|
1250
1681
|
}
|
|
1251
1682
|
}
|
|
1252
|
-
|
|
1253
|
-
if (
|
|
1254
|
-
|
|
1683
|
+
removeClass([frame], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1684
|
+
if (this.totalSelectableCount === 0) {
|
|
1685
|
+
frame.classList.add('e-uncheck');
|
|
1255
1686
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1687
|
+
else if (checkedCountForHeaderLogic === 0) {
|
|
1688
|
+
frame.classList.add('e-uncheck');
|
|
1689
|
+
}
|
|
1690
|
+
else if (checkedCountForHeaderLogic === this.totalSelectableCount) {
|
|
1691
|
+
frame.classList.add('e-check');
|
|
1692
|
+
}
|
|
1693
|
+
else {
|
|
1694
|
+
frame.classList.add('e-stop');
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Updates selection arrays (selectedItems, selectedUidMap, selectedIndexes) and visible DOM for a single record.
|
|
1699
|
+
* This is the core method for managing the state of a single checkbox.
|
|
1700
|
+
*
|
|
1701
|
+
* @param {ITreeData} currentRecord - The record to update.
|
|
1702
|
+
* @param {string} checkState - The new checkbox state ('check' | 'uncheck' | 'indeterminate').
|
|
1703
|
+
* @param {boolean} [silent] - If true, update is silent (only updates data model, no collection management or DOM update).
|
|
1704
|
+
* @returns {void}
|
|
1705
|
+
*/
|
|
1706
|
+
updateSelectedItems(currentRecord, checkState, silent) {
|
|
1707
|
+
this.buildVisibleUidMap();
|
|
1708
|
+
const uid = currentRecord.uniqueID;
|
|
1709
|
+
const uidMap = this.parent.uniqueIDCollection;
|
|
1710
|
+
const checkboxRecord = (uidMap && uid != null) ? (uidMap[String(uid)] ?
|
|
1711
|
+
uidMap[String(uid)] : currentRecord) : currentRecord;
|
|
1712
|
+
const isSummary = currentRecord.isSummaryRow === true;
|
|
1713
|
+
const previousState = checkboxRecord.checkboxState;
|
|
1714
|
+
const currentVisibleIndex = this.visibleUidIndex[String(uid)];
|
|
1715
|
+
checkboxRecord.checkboxState = checkState;
|
|
1716
|
+
if (silent) {
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
if (!isSummary && previousState !== checkState) {
|
|
1720
|
+
if (checkState === 'check') {
|
|
1721
|
+
this.checkedItemCount++;
|
|
1722
|
+
if (!this.selectedUidMap.has(String(uid))) {
|
|
1723
|
+
if (checkboxRecord.uniqueID) {
|
|
1724
|
+
this.selectedUidMap.set(String(checkboxRecord.uniqueID), true);
|
|
1725
|
+
}
|
|
1726
|
+
this.selectedItems.push(checkboxRecord);
|
|
1727
|
+
if (currentVisibleIndex !== undefined && this.selectedIndexes.indexOf(currentVisibleIndex) === -1) {
|
|
1728
|
+
this.selectedIndexes.push(currentVisibleIndex);
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1271
1731
|
}
|
|
1272
|
-
if (
|
|
1273
|
-
this.
|
|
1732
|
+
else if (previousState === 'check' || previousState === 'indeterminate') {
|
|
1733
|
+
if (this.checkedItemCount > 0) {
|
|
1734
|
+
this.checkedItemCount--;
|
|
1735
|
+
}
|
|
1736
|
+
if (checkboxRecord && checkboxRecord.uniqueID && this.selectedUidMap.has(String(checkboxRecord.uniqueID))) {
|
|
1737
|
+
this.selectedUidMap.delete(String(checkboxRecord.uniqueID));
|
|
1738
|
+
const itemIdx = this.selectedItems.indexOf(checkboxRecord);
|
|
1739
|
+
if (itemIdx !== -1) {
|
|
1740
|
+
this.selectedItems.splice(itemIdx, 1);
|
|
1741
|
+
}
|
|
1742
|
+
if (currentVisibleIndex !== undefined) {
|
|
1743
|
+
const indexInSelectedIndexes = this.selectedIndexes.indexOf(currentVisibleIndex);
|
|
1744
|
+
if (indexInSelectedIndexes > -1) {
|
|
1745
|
+
this.selectedIndexes.splice(indexInSelectedIndexes, 1);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1274
1749
|
}
|
|
1275
1750
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1751
|
+
let rowEl = null;
|
|
1752
|
+
const rowUid = currentRecord.uid;
|
|
1753
|
+
if (rowUid) {
|
|
1754
|
+
rowEl = this.parent.grid.getRowElementByUID(rowUid);
|
|
1755
|
+
}
|
|
1756
|
+
if (!rowEl) {
|
|
1757
|
+
const recordVisibleIndex = currentVisibleIndex !== undefined ? currentVisibleIndex : (typeof this.visibleUidIndex[String(uid)] === 'number' ? this.visibleUidIndex[String(uid)] : -1);
|
|
1758
|
+
if (recordVisibleIndex > -1) {
|
|
1759
|
+
rowEl = this.parent.getRows()[parseInt(recordVisibleIndex.toString(), 10)];
|
|
1760
|
+
if (!rowEl && (this.parent.frozenRows || this.parent.getFrozenColumns())) {
|
|
1761
|
+
rowEl = this.parent.getDataRows()[parseInt(recordVisibleIndex.toString(), 10)];
|
|
1762
|
+
}
|
|
1284
1763
|
}
|
|
1285
1764
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
if (
|
|
1289
|
-
|
|
1290
|
-
|
|
1765
|
+
if (rowEl) {
|
|
1766
|
+
const frame = rowEl.querySelector('.e-hierarchycheckbox .e-frame');
|
|
1767
|
+
if (frame) {
|
|
1768
|
+
removeClass([frame], ['e-check', 'e-stop', 'e-uncheck']);
|
|
1769
|
+
frame.classList.add(checkState === 'indeterminate' ? 'e-stop' : ('e-' + checkState));
|
|
1770
|
+
}
|
|
1771
|
+
const input = rowEl.querySelector('.e-treecheckselect');
|
|
1772
|
+
if (input) {
|
|
1773
|
+
input.setAttribute('aria-checked', checkState === 'check' ? 'true' :
|
|
1774
|
+
(checkState === 'uncheck' ? 'false' : 'mixed'));
|
|
1291
1775
|
}
|
|
1292
1776
|
}
|
|
1293
1777
|
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Handles various grid actions and updates selection state accordingly.
|
|
1780
|
+
* This method ensures that selection state is maintained and UI is refreshed after grid operations.
|
|
1781
|
+
*
|
|
1782
|
+
* @param {CellSaveEventArgs} args - Action arguments containing requestType and data.
|
|
1783
|
+
* @returns {void}
|
|
1784
|
+
*/
|
|
1294
1785
|
updateGridActions(args) {
|
|
1295
1786
|
const requestType = args.requestType;
|
|
1296
|
-
let childData;
|
|
1297
|
-
let childLength;
|
|
1298
1787
|
if (isCheckboxcolumn(this.parent)) {
|
|
1299
1788
|
if (this.parent.autoCheckHierarchy) {
|
|
1300
1789
|
if ((requestType === 'sorting' || requestType === 'paging')) {
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
this.selectedIndexes = [];
|
|
1305
|
-
for (let i = 0; i < childLength; i++) {
|
|
1306
|
-
if (!rows[parseInt(i.toString(), 10)].classList.contains('e-summaryrow')) {
|
|
1307
|
-
this.updateSelectedItems(childData[parseInt(i.toString(), 10)], childData[parseInt(i.toString(), 10)].checkboxState);
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1790
|
+
this.updateSelectedCollectionsAfterBulk(this.resolveHeaderSelectionList(), '');
|
|
1791
|
+
this.refreshVisibleCheckboxes();
|
|
1792
|
+
this.updateHeaderCheckboxState();
|
|
1310
1793
|
}
|
|
1311
1794
|
else if (requestType === 'delete' || args.action === 'add') {
|
|
1312
1795
|
let updatedData = [];
|
|
@@ -1318,71 +1801,68 @@ class Selection {
|
|
|
1318
1801
|
}
|
|
1319
1802
|
for (let i = 0; i < updatedData.length; i++) {
|
|
1320
1803
|
if (requestType === 'delete') {
|
|
1321
|
-
|
|
1322
|
-
const checkedIndex = this.selectedIndexes.indexOf(index);
|
|
1323
|
-
this.selectedIndexes.splice(checkedIndex, 1);
|
|
1324
|
-
this.updateSelectedItems(updatedData[parseInt(i.toString(), 10)], 'uncheck');
|
|
1804
|
+
this.updateSelectedItems(updatedData[parseInt(i.toString(), 10)], 'uncheck', false);
|
|
1325
1805
|
}
|
|
1326
1806
|
if (!isNullOrUndefined(updatedData[parseInt(i.toString(), 10)].parentItem)) {
|
|
1327
1807
|
this.updateParentSelection(updatedData[parseInt(i.toString(), 10)].parentItem);
|
|
1328
1808
|
}
|
|
1329
1809
|
}
|
|
1810
|
+
this.updateSelectedCollectionsAfterBulk(this.resolveHeaderSelectionList(true), '');
|
|
1811
|
+
this.refreshVisibleCheckboxes();
|
|
1812
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1813
|
+
this.updateHeaderCheckboxState();
|
|
1814
|
+
}
|
|
1330
1815
|
}
|
|
1331
1816
|
else if (args.requestType === 'add' && this.parent.autoCheckHierarchy) {
|
|
1332
1817
|
args.data.checkboxState = 'uncheck';
|
|
1333
1818
|
}
|
|
1334
|
-
else if (requestType === 'filtering' || requestType === 'searching' || requestType === 'refresh'
|
|
1335
|
-
|
|
1336
|
-
this.
|
|
1337
|
-
this.
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
childData.forEach((record) => {
|
|
1341
|
-
if (this.parent.enableVirtualization) {
|
|
1342
|
-
if (record.hasChildRecords && record.childRecords.length > 0) {
|
|
1343
|
-
this.updateParentSelection(record);
|
|
1344
|
-
}
|
|
1345
|
-
else {
|
|
1346
|
-
this.updateSelectedItems(record, record.checkboxState);
|
|
1347
|
-
}
|
|
1348
|
-
let child = findChildrenRecords(record);
|
|
1349
|
-
child = this.getFilteredChildRecords(child);
|
|
1350
|
-
for (let i = 0; i < child.length; i++) {
|
|
1351
|
-
if (child[parseInt(i.toString(), 10)].hasChildRecords) {
|
|
1352
|
-
this.updateParentSelection(child[parseInt(i.toString(), 10)]);
|
|
1353
|
-
}
|
|
1354
|
-
else if (!(child[parseInt(i.toString(), 10)].hasChildRecords) &&
|
|
1355
|
-
!isNullOrUndefined(child[parseInt(i.toString(), 10)])) {
|
|
1356
|
-
this.updateSelectedItems(child[parseInt(i.toString(), 10)], child[parseInt(i.toString(), 10)].checkboxState);
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
else {
|
|
1361
|
-
if (record.hasChildRecords) {
|
|
1362
|
-
this.updateParentSelection(record);
|
|
1363
|
-
}
|
|
1364
|
-
else {
|
|
1365
|
-
this.updateSelectedItems(record, record.checkboxState);
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
});
|
|
1369
|
-
this.headerSelection();
|
|
1819
|
+
else if (requestType === 'filtering' || requestType === 'searching' || requestType === 'refresh') {
|
|
1820
|
+
this.updateSelectedCollectionsAfterBulk(this.resolveHeaderSelectionList(), requestType);
|
|
1821
|
+
this.refreshVisibleCheckboxes();
|
|
1822
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1823
|
+
this.updateHeaderCheckboxState();
|
|
1824
|
+
}
|
|
1370
1825
|
}
|
|
1371
1826
|
}
|
|
1372
1827
|
else {
|
|
1373
|
-
if ((requestType === 'filtering' || requestType === 'searching' || requestType === 'refresh'
|
|
1374
|
-
|
|
1828
|
+
if ((requestType === 'filtering' || requestType === 'searching' || requestType === 'refresh' ||
|
|
1829
|
+
requestType === 'sorting' || requestType === 'paging' || requestType === 'expanding' ||
|
|
1830
|
+
requestType === 'expand' || requestType === 'collapsing' || requestType === 'collapse') && !isRemoteData(this.parent)) {
|
|
1375
1831
|
this.selectedItems = [];
|
|
1832
|
+
this.selectedUidMap = new Map();
|
|
1376
1833
|
this.selectedIndexes = [];
|
|
1834
|
+
this.refreshVisibleCheckboxes();
|
|
1835
|
+
if (this.parent.autoCheckHierarchy) {
|
|
1836
|
+
this.updateHeaderCheckboxState();
|
|
1837
|
+
}
|
|
1377
1838
|
}
|
|
1378
1839
|
}
|
|
1379
1840
|
}
|
|
1380
1841
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1842
|
+
/**
|
|
1843
|
+
* Retrieves checked record objects.
|
|
1844
|
+
* This array maintains the `ITreeData` objects in the order they were selected.
|
|
1845
|
+
*
|
|
1846
|
+
* @returns {ITreeData[]} Array of checked records.
|
|
1847
|
+
*/
|
|
1848
|
+
getCheckedrecords() { return this.selectedItems; }
|
|
1849
|
+
/**
|
|
1850
|
+
* Retrieves visible indexes of checked rows in the current view, in the order they were selected.
|
|
1851
|
+
* This method dynamically generates the list of visible indexes by iterating through `selectedItems`
|
|
1852
|
+
* (which preserves selection order) and finding their *current* visible index.
|
|
1853
|
+
*
|
|
1854
|
+
* @returns {number[]} Array of checked row indexes in selection order.
|
|
1855
|
+
*/
|
|
1384
1856
|
getCheckedRowIndexes() {
|
|
1385
|
-
|
|
1857
|
+
this.buildVisibleUidMap();
|
|
1858
|
+
const orderedVisibleIndexes = [];
|
|
1859
|
+
for (const selectedItem of this.selectedItems) {
|
|
1860
|
+
const uid = selectedItem.uniqueID;
|
|
1861
|
+
if (uid !== undefined && this.visibleUidIndex[uid] !== undefined) {
|
|
1862
|
+
orderedVisibleIndexes.push(this.visibleUidIndex[uid]);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return orderedVisibleIndexes;
|
|
1386
1866
|
}
|
|
1387
1867
|
}
|
|
1388
1868
|
|
|
@@ -1944,6 +2424,7 @@ class DataManipulation {
|
|
|
1944
2424
|
*/
|
|
1945
2425
|
destroy() {
|
|
1946
2426
|
this.removeEventListener();
|
|
2427
|
+
this.hierarchyData = null;
|
|
1947
2428
|
}
|
|
1948
2429
|
/**
|
|
1949
2430
|
* @hidden
|
|
@@ -2544,7 +3025,7 @@ class DataManipulation {
|
|
|
2544
3025
|
this.parent.parentData.push(currentData);
|
|
2545
3026
|
}
|
|
2546
3027
|
currentData.uniqueID = getUid(this.parent.element.id + '_data_');
|
|
2547
|
-
|
|
3028
|
+
this.parent.uniqueIDCollection[currentData.uniqueID] = currentData;
|
|
2548
3029
|
if (!isNullOrUndefined(parentRecords)) {
|
|
2549
3030
|
const parentData = extend$1({}, parentRecords);
|
|
2550
3031
|
delete parentData.childRecords;
|
|
@@ -3075,6 +3556,7 @@ function editAction(details, control, isSelfReference, addRowIndex, selectedInde
|
|
|
3075
3556
|
const key = control.grid.getPrimaryKeyFieldNames()[0];
|
|
3076
3557
|
const treeData = control.dataSource instanceof DataManager ?
|
|
3077
3558
|
control.dataSource.dataSource.json : control.dataSource;
|
|
3559
|
+
const gridData = control.grid.dataSource;
|
|
3078
3560
|
let modifiedData = [];
|
|
3079
3561
|
const originalData = value;
|
|
3080
3562
|
let isSkip = false;
|
|
@@ -3102,9 +3584,9 @@ function editAction(details, control, isSelfReference, addRowIndex, selectedInde
|
|
|
3102
3584
|
const keys = modifiedData[parseInt(k.toString(), 10)].taskData ?
|
|
3103
3585
|
Object.keys(modifiedData[parseInt(k.toString(), 10)].taskData) :
|
|
3104
3586
|
Object.keys(modifiedData[parseInt(k.toString(), 10)]);
|
|
3105
|
-
i = treeData.length;
|
|
3587
|
+
i = treeData.length === 0 && gridData.length === 1 ? gridData.length : treeData.length;
|
|
3106
3588
|
while (i-- && i >= 0) {
|
|
3107
|
-
if (treeData[parseInt(i.toString(), 10)][`${key}`] === modifiedData[parseInt(k.toString(), 10)][`${key}`]) {
|
|
3589
|
+
if ((treeData.length === 0 && gridData.length === 1 && gridData[parseInt(i.toString(), 10)][`${key}`] === modifiedData[parseInt(k.toString(), 10)][`${key}`]) || treeData[parseInt(i.toString(), 10)][`${key}`] === modifiedData[parseInt(k.toString(), 10)][`${key}`]) {
|
|
3108
3590
|
if (action === 'delete') {
|
|
3109
3591
|
const currentData = treeData[parseInt(i.toString(), 10)];
|
|
3110
3592
|
treeData.splice(i, 1);
|
|
@@ -3148,7 +3630,10 @@ function editAction(details, control, isSelfReference, addRowIndex, selectedInde
|
|
|
3148
3630
|
else if (action === 'add' || action === 'batchsave') {
|
|
3149
3631
|
let index;
|
|
3150
3632
|
if (control.editSettings.newRowPosition === 'Child') {
|
|
3151
|
-
if (
|
|
3633
|
+
if (treeData.length === 0 && gridData.length === 1) {
|
|
3634
|
+
treeData.push(originalData.taskData);
|
|
3635
|
+
}
|
|
3636
|
+
else if (isSelfReference) {
|
|
3152
3637
|
originalData.taskData[`${control.parentIdMapping}`] = treeData[parseInt(i.toString(), 10)][`${control.idMapping}`];
|
|
3153
3638
|
treeData.splice(i + 1, 0, originalData.taskData);
|
|
3154
3639
|
}
|
|
@@ -3223,6 +3708,9 @@ function addAction(details, treeData, control, isSelfReference, addRowIndex, sel
|
|
|
3223
3708
|
value = extend$1({}, addRowRecord);
|
|
3224
3709
|
value = getPlainData(value);
|
|
3225
3710
|
}
|
|
3711
|
+
else if (currentViewRecords.length === 0) {
|
|
3712
|
+
value = getPlainData(value);
|
|
3713
|
+
}
|
|
3226
3714
|
else {
|
|
3227
3715
|
value = extend$1({}, currentViewRecords[addRowIndex + 1]);
|
|
3228
3716
|
value = getPlainData(value);
|
|
@@ -3236,8 +3724,8 @@ function addAction(details, treeData, control, isSelfReference, addRowIndex, sel
|
|
|
3236
3724
|
}
|
|
3237
3725
|
else {
|
|
3238
3726
|
const primaryKeys = control.grid.getPrimaryKeyFieldNames()[0];
|
|
3239
|
-
const currentdata = currentViewRecords[parseInt(addRowIndex.toString(), 10)];
|
|
3240
|
-
if (!isNullOrUndefined(currentdata) && currentdata[`${primaryKeys}`] === details.value[`${primaryKeys}`] || selectedIndex !== -1) {
|
|
3727
|
+
const currentdata = currentViewRecords.length > 0 ? currentViewRecords[parseInt(addRowIndex.toString(), 10)] : [];
|
|
3728
|
+
if (!isNullOrUndefined(currentdata) && currentdata[`${primaryKeys}`] === details.value[`${primaryKeys}`] || selectedIndex !== -1 && treeData.length !== 0) {
|
|
3241
3729
|
value = extend$1({}, currentdata);
|
|
3242
3730
|
}
|
|
3243
3731
|
else {
|
|
@@ -3527,7 +4015,9 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3527
4015
|
constructor(options, element) {
|
|
3528
4016
|
super(options, element);
|
|
3529
4017
|
this.dataResults = {};
|
|
4018
|
+
/** @hidden */
|
|
3530
4019
|
this.uniqueIDCollection = {};
|
|
4020
|
+
/** @hidden */
|
|
3531
4021
|
this.uniqueIDFilterCollection = {};
|
|
3532
4022
|
this.changedRecords = 'changedRecords';
|
|
3533
4023
|
this.deletedRecords = 'deletedRecords';
|
|
@@ -3537,6 +4027,8 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3537
4027
|
this.modifiedRecords = [];
|
|
3538
4028
|
this.stackedHeader = false;
|
|
3539
4029
|
this.freezeColumnRefresh = true;
|
|
4030
|
+
this.componentRefresh = Component.prototype.refresh;
|
|
4031
|
+
this.isComponentRefresh = false;
|
|
3540
4032
|
this.objectEqualityChecker = (old, current) => {
|
|
3541
4033
|
if (old) {
|
|
3542
4034
|
const keys = Object.keys(old);
|
|
@@ -3585,7 +4077,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3585
4077
|
/* eslint-disable */
|
|
3586
4078
|
excelExport(excelExportProperties, isMultipleExport, workbook, isBlob) {
|
|
3587
4079
|
/* eslint-enable */
|
|
3588
|
-
return this.excelExportModule.Map(excelExportProperties, isMultipleExport, workbook, isBlob, false);
|
|
4080
|
+
return this.allowExcelExport ? this.excelExportModule.Map(excelExportProperties, isMultipleExport, workbook, isBlob, false) : null;
|
|
3589
4081
|
}
|
|
3590
4082
|
/**
|
|
3591
4083
|
* Exports the TreeGrid data to a CSV file.
|
|
@@ -3599,7 +4091,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3599
4091
|
/* eslint-disable */
|
|
3600
4092
|
csvExport(excelExportProperties, isMultipleExport, workbook, isBlob) {
|
|
3601
4093
|
/* eslint-enable */
|
|
3602
|
-
return this.excelExportModule.Map(excelExportProperties, isMultipleExport, workbook, isBlob, true);
|
|
4094
|
+
return this.allowExcelExport ? this.excelExportModule.Map(excelExportProperties, isMultipleExport, workbook, isBlob, true) : null;
|
|
3603
4095
|
}
|
|
3604
4096
|
/**
|
|
3605
4097
|
* Exports the TreeGrid data to a PDF document.
|
|
@@ -3611,7 +4103,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3611
4103
|
* @returns {Promise<any>} - Returns a promise that resolves with the result of the export action.
|
|
3612
4104
|
*/
|
|
3613
4105
|
pdfExport(pdfExportProperties, isMultipleExport, pdfDoc, isBlob) {
|
|
3614
|
-
return this.pdfExportModule.Map(pdfExportProperties, isMultipleExport, pdfDoc, isBlob);
|
|
4106
|
+
return this.allowPdfExport ? this.pdfExportModule.Map(pdfExportProperties, isMultipleExport, pdfDoc, isBlob) : null;
|
|
3615
4107
|
}
|
|
3616
4108
|
/**
|
|
3617
4109
|
* Sends a POST request to export the TreeGrid to an Excel file on the server side.
|
|
@@ -3731,6 +4223,26 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3731
4223
|
getModuleName() {
|
|
3732
4224
|
return 'treegrid';
|
|
3733
4225
|
}
|
|
4226
|
+
/**
|
|
4227
|
+
* Initiates a complete refresh of the TreeGrid's column and layout.
|
|
4228
|
+
*
|
|
4229
|
+
* This method forces a full re-render of the TreeGrid, ensuring that any dynamic
|
|
4230
|
+
* changes to columns or layout are immediately reflected.
|
|
4231
|
+
*
|
|
4232
|
+
* @returns {void}
|
|
4233
|
+
*/
|
|
4234
|
+
refreshLayout() {
|
|
4235
|
+
this.componentRefresh();
|
|
4236
|
+
}
|
|
4237
|
+
/**
|
|
4238
|
+
* @param {Object} prop - Defines the property
|
|
4239
|
+
* @param {boolean} muteOnChange - Defines the mute on change
|
|
4240
|
+
* @returns {void}
|
|
4241
|
+
* @private
|
|
4242
|
+
*/
|
|
4243
|
+
setProperties(prop, muteOnChange) {
|
|
4244
|
+
super.setProperties(prop, muteOnChange);
|
|
4245
|
+
}
|
|
3734
4246
|
/**
|
|
3735
4247
|
* For internal use only - Initialize the event handler;
|
|
3736
4248
|
*
|
|
@@ -3738,6 +4250,9 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3738
4250
|
* @returns {void}
|
|
3739
4251
|
*/
|
|
3740
4252
|
preRender() {
|
|
4253
|
+
if (this.isComponentRefresh) {
|
|
4254
|
+
this.grid = new Grid();
|
|
4255
|
+
}
|
|
3741
4256
|
this.TreeGridLocale();
|
|
3742
4257
|
this.initProperties();
|
|
3743
4258
|
this.defaultLocale = {
|
|
@@ -3907,7 +4422,10 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3907
4422
|
}
|
|
3908
4423
|
}
|
|
3909
4424
|
else {
|
|
3910
|
-
this.
|
|
4425
|
+
const contentTableBody = this.grid.getContent().querySelector('.e-table tbody');
|
|
4426
|
+
if (parentTarget && contentTableBody && parentTarget !== contentTableBody.lastElementChild) {
|
|
4427
|
+
this.clearSelection();
|
|
4428
|
+
}
|
|
3911
4429
|
}
|
|
3912
4430
|
}
|
|
3913
4431
|
}
|
|
@@ -3978,6 +4496,8 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
3978
4496
|
this.isExpandAll = false;
|
|
3979
4497
|
this.isCollapseAll = false;
|
|
3980
4498
|
this.freezeColumnRefresh = true;
|
|
4499
|
+
this.componentRefresh = Component.prototype.refresh;
|
|
4500
|
+
this.isComponentRefresh = false;
|
|
3981
4501
|
this.keyConfigs = {
|
|
3982
4502
|
ctrlDownArrow: 'ctrl+downarrow',
|
|
3983
4503
|
ctrlUpArrow: 'ctrl+uparrow',
|
|
@@ -4296,6 +4816,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
4296
4816
|
if (this.isIndentEnabled) {
|
|
4297
4817
|
this.refreshToolbarItems();
|
|
4298
4818
|
}
|
|
4819
|
+
this.updateColumnModel();
|
|
4299
4820
|
this.wireEvents();
|
|
4300
4821
|
this.renderComplete();
|
|
4301
4822
|
const destroyTemplate = 'destroyTemplate';
|
|
@@ -4345,6 +4866,15 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
4345
4866
|
if (this.allowSelection && !isNullOrUndefined(this.rowTemplate)) {
|
|
4346
4867
|
failureCases.push('Selection is not supported in RowTemplate');
|
|
4347
4868
|
}
|
|
4869
|
+
if (!this.allowExcelExport && this.action === 'csvExport') {
|
|
4870
|
+
failureCases.push('CSV export is not allowed when allowExcelExport is disabled.');
|
|
4871
|
+
}
|
|
4872
|
+
if (!this.allowPdfExport && this.action === 'pdfExport') {
|
|
4873
|
+
failureCases.push('PDF export is not allowed when allowPdfExport is disabled');
|
|
4874
|
+
}
|
|
4875
|
+
if (!this.allowExcelExport && this.action === 'excelExport') {
|
|
4876
|
+
failureCases.push('Excel export is not allowed when allowExcelExport is disabled.');
|
|
4877
|
+
}
|
|
4348
4878
|
if (this.treeColumnIndex >= this.columns.length) {
|
|
4349
4879
|
failureCases.push('TreeColumnIndex value should not exceed the total column count.');
|
|
4350
4880
|
}
|
|
@@ -4499,6 +5029,8 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
4499
5029
|
this.grid.frozenRows = this.frozenRows;
|
|
4500
5030
|
this.grid.frozenColumns = this.frozenColumns;
|
|
4501
5031
|
this.grid.clipMode = getActualProperties(this.clipMode);
|
|
5032
|
+
this.grid.enableColumnSpan = this.enableColumnSpan;
|
|
5033
|
+
this.grid.enableRowSpan = this.enableRowSpan;
|
|
4502
5034
|
const templateInstance = 'templateDotnetInstance';
|
|
4503
5035
|
this.grid[`${templateInstance}`] = this[`${templateInstance}`];
|
|
4504
5036
|
const isJsComponent = 'isJsComponent';
|
|
@@ -4973,12 +5505,12 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
4973
5505
|
this.grid.refresh();
|
|
4974
5506
|
}
|
|
4975
5507
|
if (args.action === 'filter') {
|
|
4976
|
-
if (!args.isCollapseMaintain && this.filterModule['currentFilterObject'] !== '' && this.enableVirtualization && !this.initialRender && !(isRemoteData(this) && this.enableVirtualization)) {
|
|
5508
|
+
if (!args.isCollapseMaintain && this.filterModule['currentFilterObject'] !== '' && this.enableVirtualization && !this.initialRender && !this.expandStateMapping && !(isRemoteData(this) && this.enableVirtualization)) {
|
|
4977
5509
|
this.expandAll();
|
|
4978
5510
|
}
|
|
4979
5511
|
}
|
|
4980
5512
|
if (args.requestType === 'searching') {
|
|
4981
|
-
if (!args.isCollapseMaintain && this.searchSettings.key !== '' && this.enableVirtualization && !this.initialRender && !(isRemoteData(this) && this.enableVirtualization)) {
|
|
5513
|
+
if (!args.isCollapseMaintain && this.searchSettings.key !== '' && this.enableVirtualization && !this.initialRender && !this.expandStateMapping && !(isRemoteData(this) && this.enableVirtualization)) {
|
|
4982
5514
|
this.expandAll();
|
|
4983
5515
|
}
|
|
4984
5516
|
}
|
|
@@ -5313,11 +5845,14 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5313
5845
|
onPropertyChanged(newProp) {
|
|
5314
5846
|
const properties = Object.keys(newProp);
|
|
5315
5847
|
let requireRefresh = false;
|
|
5316
|
-
if (properties.indexOf('columns') > -1 && !isNullOrUndefined(newProp.columns)) {
|
|
5317
|
-
this.refreshColumns();
|
|
5318
|
-
}
|
|
5319
5848
|
for (const prop of properties) {
|
|
5320
5849
|
switch (prop) {
|
|
5850
|
+
case 'columns':
|
|
5851
|
+
if (!isNullOrUndefined(newProp.columns)) {
|
|
5852
|
+
this.refreshColumns();
|
|
5853
|
+
}
|
|
5854
|
+
requireRefresh = true;
|
|
5855
|
+
break;
|
|
5321
5856
|
case 'treeColumnIndex':
|
|
5322
5857
|
this.grid.refreshColumns();
|
|
5323
5858
|
break;
|
|
@@ -5528,8 +6063,19 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5528
6063
|
}
|
|
5529
6064
|
this.grid.editSettings = this.getGridEditSettings();
|
|
5530
6065
|
break;
|
|
6066
|
+
case 'enableRowSpan':
|
|
6067
|
+
case 'enableColumnSpan':
|
|
6068
|
+
this.grid.enableRowSpan = this.enableRowSpan;
|
|
6069
|
+
this.grid.enableColumnSpan = this.enableColumnSpan;
|
|
6070
|
+
this.refreshColumns();
|
|
6071
|
+
break;
|
|
5531
6072
|
}
|
|
5532
|
-
|
|
6073
|
+
}
|
|
6074
|
+
if (requireRefresh) {
|
|
6075
|
+
if (this.isFrozenGrid()) {
|
|
6076
|
+
this.refreshLayout();
|
|
6077
|
+
}
|
|
6078
|
+
else {
|
|
5533
6079
|
this.grid.refresh();
|
|
5534
6080
|
}
|
|
5535
6081
|
}
|
|
@@ -5550,6 +6096,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5550
6096
|
* @returns {void}
|
|
5551
6097
|
*/
|
|
5552
6098
|
destroy() {
|
|
6099
|
+
this.isComponentRefresh = true;
|
|
5553
6100
|
const treeGridElement = this.element;
|
|
5554
6101
|
if (!treeGridElement) {
|
|
5555
6102
|
return;
|
|
@@ -5560,15 +6107,20 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5560
6107
|
this.unwireEvents();
|
|
5561
6108
|
}
|
|
5562
6109
|
this.removeListener();
|
|
5563
|
-
if (
|
|
5564
|
-
|
|
6110
|
+
if (this.dataModule) {
|
|
6111
|
+
this.dataModule.destroy();
|
|
5565
6112
|
}
|
|
5566
6113
|
if (this.grid) {
|
|
6114
|
+
this.grid.dataSource = null;
|
|
5567
6115
|
this.grid.destroy();
|
|
5568
6116
|
}
|
|
5569
|
-
if (
|
|
5570
|
-
|
|
6117
|
+
if (hasTreeGridChild) {
|
|
6118
|
+
super.destroy();
|
|
5571
6119
|
}
|
|
6120
|
+
this.infiniteScrollData = null;
|
|
6121
|
+
this.remoteCollapsedData = null;
|
|
6122
|
+
this.remoteExpandedData = null;
|
|
6123
|
+
this.parentData = null;
|
|
5572
6124
|
const modules = ['dataModule', 'sortModule', 'renderModule', 'filterModule', 'printModule', 'clipboardModule',
|
|
5573
6125
|
'excelExportModule', 'pdfExportModule', 'toolbarModule', 'summaryModule', 'reorderModule', 'resizeModule',
|
|
5574
6126
|
'pagerModule', 'keyboardModule', 'columnMenuModule', 'contextMenuModule', 'editModule', 'virtualScrollModule',
|
|
@@ -5578,6 +6130,9 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5578
6130
|
this[modules[parseInt(i.toString(), 10)]] = null;
|
|
5579
6131
|
}
|
|
5580
6132
|
}
|
|
6133
|
+
this.dataResults = null;
|
|
6134
|
+
this.uniqueIDCollection = {};
|
|
6135
|
+
this.uniqueIDFilterCollection = {};
|
|
5581
6136
|
this.element.innerHTML = '';
|
|
5582
6137
|
this.grid = null;
|
|
5583
6138
|
}
|
|
@@ -5718,7 +6273,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
5718
6273
|
/**
|
|
5719
6274
|
* Adds a new record to the TreeGrid at the specified position or default location.
|
|
5720
6275
|
*
|
|
5721
|
-
* @param {Object} data - Object containing
|
|
6276
|
+
* @param {Object | Object[]} data - Object containing data for a single record, or an array of objects for creating multiple records. If omitted, an empty row is added.
|
|
5722
6277
|
* @param {number} index - The index at which the new row should be added.
|
|
5723
6278
|
* @param {RowPosition} position - Specifies the position of the new row (e.g., before, after or child).
|
|
5724
6279
|
*
|
|
@@ -6527,7 +7082,9 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
6527
7082
|
if (isNullOrUndefined(refreshUI) || refreshUI) {
|
|
6528
7083
|
this.grid.columns = this.getGridColumns(this.columns);
|
|
6529
7084
|
this.getTreeColumn();
|
|
6530
|
-
this.
|
|
7085
|
+
if (!this.isFrozenGrid()) {
|
|
7086
|
+
this.grid.refreshColumns();
|
|
7087
|
+
}
|
|
6531
7088
|
}
|
|
6532
7089
|
else {
|
|
6533
7090
|
this.grid.setProperties({ columns: this.getGridColumns(this.columns) }, true);
|
|
@@ -7059,7 +7616,8 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7059
7616
|
if (rows.length) {
|
|
7060
7617
|
for (let i = 0; i < rows.length; i++) {
|
|
7061
7618
|
if (action === 'collapse') {
|
|
7062
|
-
|
|
7619
|
+
const currentRecordIndx = this.frozenRows ? this.getCurrentViewRecords()[parseInt(rows[parseInt(i.toString(), 10)].getAttribute('aria-rowindex'), 10) - 1] : this.getCurrentViewRecords()[rows[parseInt(i.toString(), 10)].rowIndex];
|
|
7620
|
+
if (!isNullOrUndefined(currentRecordIndx)) {
|
|
7063
7621
|
this.collapseRow(rows[parseInt(i.toString(), 10)]);
|
|
7064
7622
|
}
|
|
7065
7623
|
}
|
|
@@ -7183,8 +7741,9 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7183
7741
|
}
|
|
7184
7742
|
const lastrowIdx = this.getVisibleRecords()[this.getVisibleRecords().length - 1]['index'];
|
|
7185
7743
|
const lastRow = this.getRowByIndex(lastrowIdx);
|
|
7186
|
-
|
|
7187
|
-
|
|
7744
|
+
const borderElement = lastRow ? lastRow.nextElementSibling ? lastRow.nextElementSibling.classList.contains('e-detailrow') ? lastRow.nextElementSibling : lastRow : lastRow : null;
|
|
7745
|
+
if (this.grid.getContentTable().clientHeight <= this.grid.getContent().clientHeight && !isNullOrUndefined(borderElement) && !borderElement.cells[0].classList.contains('e-lastrowcell')) {
|
|
7746
|
+
this.lastRowBorder(borderElement, true);
|
|
7188
7747
|
}
|
|
7189
7748
|
}
|
|
7190
7749
|
if (isCountRequired(this) && action === 'expand') {
|
|
@@ -7345,12 +7904,16 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7345
7904
|
}
|
|
7346
7905
|
localExpand(action, row, record) {
|
|
7347
7906
|
let rows;
|
|
7907
|
+
const detailRow = row.nextElementSibling ? row.nextElementSibling.classList.contains('e-detailrow') ? row.nextElementSibling : null : null;
|
|
7348
7908
|
const childRecords = this.grid.currentViewData.filter((e) => {
|
|
7349
7909
|
return e.parentUniqueID === record.uniqueID;
|
|
7350
7910
|
});
|
|
7351
7911
|
if (this.isPixelHeight() && row.cells[0].classList.contains('e-lastrowcell')) {
|
|
7352
7912
|
this.lastRowBorder(row, false);
|
|
7353
7913
|
}
|
|
7914
|
+
else if (this.isPixelHeight() && detailRow && detailRow.cells[0].classList.contains('e-lastrowcell')) {
|
|
7915
|
+
this.lastRowBorder(row.nextElementSibling, false);
|
|
7916
|
+
}
|
|
7354
7917
|
let movableRows;
|
|
7355
7918
|
let freezeRightRows;
|
|
7356
7919
|
let gridRows = this.getRows();
|
|
@@ -7553,6 +8116,7 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7553
8116
|
this.on('updateResults', this.updateResultModel, this);
|
|
7554
8117
|
this.grid.on('initial-end', this.afterGridRender, this);
|
|
7555
8118
|
this.grid.on('partial-filter-update', this.partialFilterUpdate, this);
|
|
8119
|
+
this.grid.on('get-row-cells', this.getCellsByTableName, this);
|
|
7556
8120
|
}
|
|
7557
8121
|
updateResultModel(returnResult) {
|
|
7558
8122
|
this.dataResults = returnResult;
|
|
@@ -7569,6 +8133,16 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7569
8133
|
this.grid.off('initial-end', this.afterGridRender);
|
|
7570
8134
|
this.grid.off('last-rowcell-border-updated', this.lastRowCellBorderUpdated);
|
|
7571
8135
|
this.grid.off('partial-filter-update', this.partialFilterUpdate);
|
|
8136
|
+
this.grid.off('get-row-cells', this.getCellsByTableName);
|
|
8137
|
+
}
|
|
8138
|
+
getCellsByTableName(args) {
|
|
8139
|
+
if (!Array.isArray(args.elements)) {
|
|
8140
|
+
args.elements = [];
|
|
8141
|
+
}
|
|
8142
|
+
if (args.rowIndex < this.grid.getDataRows().length) {
|
|
8143
|
+
const cells = [].slice.call(this.grid.getDataRows()[parseInt(args.rowIndex.toString(), 10)].getElementsByClassName('e-rowcell'));
|
|
8144
|
+
Array.prototype.push.apply(args.elements, cells);
|
|
8145
|
+
}
|
|
7572
8146
|
}
|
|
7573
8147
|
partialFilterUpdate(args) {
|
|
7574
8148
|
const gridFiltered = args.gridFiltered;
|
|
@@ -7993,6 +8567,53 @@ let TreeGrid = TreeGrid_1 = class TreeGrid extends Component {
|
|
|
7993
8567
|
this.rowDragAndDropModule[this.indentOutdentAction](record, 'outdent');
|
|
7994
8568
|
}
|
|
7995
8569
|
}
|
|
8570
|
+
/**
|
|
8571
|
+
* Calculates and returns the optimal page size that fits the current height of the TreeGrid's container.
|
|
8572
|
+
*
|
|
8573
|
+
* @param {number | string } containerHeight - (Optional) The height of the container - i.e. the complete TreeGrid height, which can be a number (in pixels) or a string.
|
|
8574
|
+
* @returns {number} returns the page size
|
|
8575
|
+
*/
|
|
8576
|
+
getPageSizeByHeight(containerHeight) {
|
|
8577
|
+
if (isNullOrUndefined(containerHeight)) {
|
|
8578
|
+
const treegridControlElement = document.getElementById(this.element.id);
|
|
8579
|
+
if (treegridControlElement) {
|
|
8580
|
+
containerHeight = treegridControlElement.clientHeight;
|
|
8581
|
+
}
|
|
8582
|
+
else {
|
|
8583
|
+
const root = this.element;
|
|
8584
|
+
containerHeight = root ? (root.offsetHeight || root.clientHeight || 0) : 0;
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
if ((this.allowTextWrap && this.textWrapSettings.wrapMode === 'Header') || (!this.allowTextWrap)) {
|
|
8588
|
+
let pagesize = 0;
|
|
8589
|
+
if (typeof containerHeight === 'string' && containerHeight.indexOf('%') !== -1) {
|
|
8590
|
+
containerHeight = parseInt(containerHeight, 10) / 100 * this.element.clientHeight;
|
|
8591
|
+
}
|
|
8592
|
+
const nonContentHeight = this.grid['getNoncontentHeight']() + this.grid.getRowHeight();
|
|
8593
|
+
if (containerHeight > nonContentHeight) {
|
|
8594
|
+
let contentHeight = 0;
|
|
8595
|
+
let calcNonContentHeight = this.grid['getNoncontentHeight']();
|
|
8596
|
+
const pagerMsg = document.getElementsByClassName('e-pagerexternalmsg')[0];
|
|
8597
|
+
if (pagerMsg) {
|
|
8598
|
+
calcNonContentHeight += pagerMsg.clientHeight;
|
|
8599
|
+
}
|
|
8600
|
+
contentHeight = containerHeight - calcNonContentHeight;
|
|
8601
|
+
pagesize = (contentHeight / this.grid.getRowHeight());
|
|
8602
|
+
}
|
|
8603
|
+
if (this.frozenRows > 0) {
|
|
8604
|
+
pagesize = pagesize + this.frozenRows;
|
|
8605
|
+
}
|
|
8606
|
+
if (pagesize > 0) {
|
|
8607
|
+
return Math.floor(pagesize);
|
|
8608
|
+
}
|
|
8609
|
+
else {
|
|
8610
|
+
return 0;
|
|
8611
|
+
}
|
|
8612
|
+
}
|
|
8613
|
+
else {
|
|
8614
|
+
return 0;
|
|
8615
|
+
}
|
|
8616
|
+
}
|
|
7996
8617
|
};
|
|
7997
8618
|
__decorate$c([
|
|
7998
8619
|
Property(0)
|
|
@@ -8207,6 +8828,12 @@ __decorate$c([
|
|
|
8207
8828
|
__decorate$c([
|
|
8208
8829
|
Property(false)
|
|
8209
8830
|
], TreeGrid.prototype, "allowPdfExport", void 0);
|
|
8831
|
+
__decorate$c([
|
|
8832
|
+
Property(false)
|
|
8833
|
+
], TreeGrid.prototype, "enableColumnSpan", void 0);
|
|
8834
|
+
__decorate$c([
|
|
8835
|
+
Property(false)
|
|
8836
|
+
], TreeGrid.prototype, "enableRowSpan", void 0);
|
|
8210
8837
|
__decorate$c([
|
|
8211
8838
|
Event()
|
|
8212
8839
|
], TreeGrid.prototype, "created", void 0);
|
|
@@ -8708,6 +9335,9 @@ class RowDD {
|
|
|
8708
9335
|
this.selectedItem = isNullOrUndefined(record) ?
|
|
8709
9336
|
tObj.getCurrentViewRecords()[parseInt(selectedItemIndex.toString(), 10)] : record;
|
|
8710
9337
|
const primaryKeyField = this.parent.getPrimaryKeyFieldNames()[0];
|
|
9338
|
+
if (!primaryKeyField) {
|
|
9339
|
+
return;
|
|
9340
|
+
}
|
|
8711
9341
|
const rowIndex = this.parent.grid.getRowIndexByPrimaryKey(this.selectedItem[`${primaryKeyField}`]);
|
|
8712
9342
|
this.selectedRow = this.parent[this.selectedRows] = selectedItemIndex !== -1 ?
|
|
8713
9343
|
this.parent.getSelectedRows()[0]
|
|
@@ -11645,7 +12275,7 @@ class Aggregate {
|
|
|
11645
12275
|
const value = types[parseInt(i.toString(), 10)] !== 'Custom' ? val[`${key}`] : val;
|
|
11646
12276
|
single[`${disp}`] = single[`${disp}`] || {};
|
|
11647
12277
|
single[`${disp}`][`${key}`] = value;
|
|
11648
|
-
single[`${disp}`][types[parseInt(i.toString(), 10)]] = !isNullOrUndefined(val) ? formatFn(value) : ' ';
|
|
12278
|
+
single[`${disp}`][types[parseInt(i.toString(), 10)]] = (!isNullOrUndefined(val) && !isNullOrUndefined(value)) ? formatFn(value) : ' ';
|
|
11649
12279
|
}
|
|
11650
12280
|
helper.format = summaryColumn.getFormatter();
|
|
11651
12281
|
const cellElement = createElement('td', {
|
|
@@ -11869,6 +12499,7 @@ class ContextMenu {
|
|
|
11869
12499
|
addEventListener() {
|
|
11870
12500
|
this.parent.on('contextMenuOpen', this.contextMenuOpen, this);
|
|
11871
12501
|
this.parent.on('contextMenuClick', this.contextMenuClick, this);
|
|
12502
|
+
this.parent.on('contextMenuItemClick', this.contextMenuItemClick, this);
|
|
11872
12503
|
}
|
|
11873
12504
|
/**
|
|
11874
12505
|
* @hidden
|
|
@@ -11880,6 +12511,21 @@ class ContextMenu {
|
|
|
11880
12511
|
}
|
|
11881
12512
|
this.parent.off('contextMenuOpen', this.contextMenuOpen);
|
|
11882
12513
|
this.parent.off('contextMenuClick', this.contextMenuClick);
|
|
12514
|
+
this.parent.off('contextMenuItemClick', this.contextMenuItemClick);
|
|
12515
|
+
}
|
|
12516
|
+
contextMenuItemClick(args) {
|
|
12517
|
+
const id = args.item && args.item.id ? args.item.id : '';
|
|
12518
|
+
const delId = this.parent.element.id + '_gridcontrol_cmenu_Delete';
|
|
12519
|
+
if (id !== delId) {
|
|
12520
|
+
return;
|
|
12521
|
+
}
|
|
12522
|
+
if (this.parent.getSelectedRecords()[0].hasChildRecords || this.parent.getSelectedRecords().length > 1) {
|
|
12523
|
+
this.parent.deleteRecord();
|
|
12524
|
+
}
|
|
12525
|
+
else {
|
|
12526
|
+
this.parent.deleteRow(this.parent.getSelectedRows()[0]);
|
|
12527
|
+
}
|
|
12528
|
+
args.cancel = true;
|
|
11883
12529
|
}
|
|
11884
12530
|
contextMenuOpen(args) {
|
|
11885
12531
|
const addRow = select('#' + this.parent.element.id + '_gridcontrol_cmenu_AddRow', args.element);
|
|
@@ -12261,13 +12907,22 @@ class BatchEdit {
|
|
|
12261
12907
|
focusModule.getContent().matrix.matrix = this.matrix;
|
|
12262
12908
|
}
|
|
12263
12909
|
else {
|
|
12264
|
-
|
|
12910
|
+
if (this.parent.frozenRows) {
|
|
12911
|
+
actualIndex = this.batchIndex;
|
|
12912
|
+
}
|
|
12913
|
+
else if (this.parent.editModule.isAddedMultipleRowsByMethod) {
|
|
12914
|
+
actualIndex = e.index;
|
|
12915
|
+
}
|
|
12916
|
+
else {
|
|
12917
|
+
actualIndex = table.getElementsByClassName('e-batchrow')[0].rowIndex;
|
|
12918
|
+
}
|
|
12265
12919
|
// if (this.parent.frozenRows || this.parent.frozenColumns) {
|
|
12266
12920
|
// actualIndex = this.batchIndex;
|
|
12267
12921
|
// }
|
|
12268
12922
|
}
|
|
12269
12923
|
focusModule.getContent().matrix.current = [actualIndex, focusModule.getContent().matrix.current[1]];
|
|
12270
|
-
if (this.parent.editModule['isAddedRowByMethod'] && !isNullOrUndefined(this.parent.editModule['addRowIndex']) &&
|
|
12924
|
+
if (this.parent.editModule['isAddedRowByMethod'] && !isNullOrUndefined(this.parent.editModule['addRowIndex']) &&
|
|
12925
|
+
!this.parent.editModule['isAddedRowByContextMenu'] && !this.parent.editModule.isAddedMultipleRowsByMethod) {
|
|
12271
12926
|
const newlyAddedRecords = this.parent.getBatchChanges()['addedRecords'];
|
|
12272
12927
|
const index = parseInt(this.parent.getContentTable().getElementsByClassName('e-insertedrow')[newlyAddedRecords.length - 1].getAttribute('aria-rowindex'), 10) - 1;
|
|
12273
12928
|
this.batchRecords.splice(index, 0, newlyAddedRecords[newlyAddedRecords.length - 1]);
|
|
@@ -12475,7 +13130,7 @@ class BatchEdit {
|
|
|
12475
13130
|
}
|
|
12476
13131
|
else {
|
|
12477
13132
|
const totalRecords = extendArray(data);
|
|
12478
|
-
if (totalRecords.length) {
|
|
13133
|
+
if (totalRecords.length && currentViewRecords.length !== 0) {
|
|
12479
13134
|
const startIndex = totalRecords.map((e) => { return e[`${primarykey}`]; })
|
|
12480
13135
|
.indexOf(currentViewRecords[0][`${primarykey}`]);
|
|
12481
13136
|
const endIndex = startIndex + this.parent.grid.pageSettings.pageSize;
|
|
@@ -12507,7 +13162,12 @@ class BatchEdit {
|
|
|
12507
13162
|
this.parent.editModule['previousNewRowPosition'] = rowPosition;
|
|
12508
13163
|
}
|
|
12509
13164
|
addRecords[parseInt(i.toString(), 10)].taskData = taskData;
|
|
12510
|
-
|
|
13165
|
+
if (this.batchAddRowRecord.length > 1) {
|
|
13166
|
+
addRowRecord = this.batchAddRowRecord[parseInt(i.toString(), 10)];
|
|
13167
|
+
}
|
|
13168
|
+
else {
|
|
13169
|
+
addRowRecord = this.batchAddRowRecord[0];
|
|
13170
|
+
}
|
|
12511
13171
|
if (isNullOrUndefined(addRowRecord)) {
|
|
12512
13172
|
addRowRecord = this.batchAddRowRecord[i - 1];
|
|
12513
13173
|
}
|
|
@@ -12522,6 +13182,10 @@ class BatchEdit {
|
|
|
12522
13182
|
if (isNullOrUndefined(addRecords[parseInt(i.toString(), 10)].index)) {
|
|
12523
13183
|
addRowIndex = 0;
|
|
12524
13184
|
}
|
|
13185
|
+
if (this.parent.editModule.isAddedMultipleRowsByMethod && this.isSelfReference && (this.parent.editSettings.newRowPosition === 'Above' || this.parent.editSettings.newRowPosition === 'Below')) {
|
|
13186
|
+
addRowIndex = args.index;
|
|
13187
|
+
addRowRecord = this.parent.flatData[args.index];
|
|
13188
|
+
}
|
|
12525
13189
|
if (this.parent.editSettings.newRowPosition !== 'Top' && this.parent.editSettings.newRowPosition !== 'Bottom') {
|
|
12526
13190
|
if (isNullOrUndefined(addRecords[parseInt(i.toString(), 10)].parentItem) && this.selectedIndex === -1) {
|
|
12527
13191
|
selectedIndex = -1;
|
|
@@ -12648,6 +13312,7 @@ class Edit {
|
|
|
12648
13312
|
this.isAddedRowByMethod = false;
|
|
12649
13313
|
this.isAddedRowByContextMenu = false;
|
|
12650
13314
|
this.isIndexUndefined = false;
|
|
13315
|
+
this.isAddedMultipleRowsByMethod = false;
|
|
12651
13316
|
Grid.Inject(Edit$1);
|
|
12652
13317
|
this.parent = parent;
|
|
12653
13318
|
this.isSelfReference = !isNullOrUndefined(parent.parentIdMapping);
|
|
@@ -13304,7 +13969,8 @@ class Edit {
|
|
|
13304
13969
|
}
|
|
13305
13970
|
}
|
|
13306
13971
|
}
|
|
13307
|
-
if (this.parent.editSettings.mode === 'Batch' && !isNullOrUndefined(this.addRowIndex) && this.addRowIndex !== -1 &&
|
|
13972
|
+
if (this.parent.editSettings.mode === 'Batch' && !isNullOrUndefined(this.addRowIndex) && this.addRowIndex !== -1 &&
|
|
13973
|
+
!this.isAddedMultipleRowsByMethod && this['isAddedRowByMethod'] && !this.isAddedRowByContextMenu) {
|
|
13308
13974
|
index = this.batchEditModule.getAddRowIndex();
|
|
13309
13975
|
this.selectedIndex = this.batchEditModule.getSelectedIndex();
|
|
13310
13976
|
const batchAddedRecords = this.parent.getBatchChanges()['addedRecords'];
|
|
@@ -13326,6 +13992,28 @@ class Edit {
|
|
|
13326
13992
|
this.batchEditModule['batchAddRowRecord'].push(this.batchEditModule['addRowRecord']);
|
|
13327
13993
|
this.batchEditModule['batchAddedRecords'].push(args['data']);
|
|
13328
13994
|
}
|
|
13995
|
+
else if (this.parent.editSettings.mode === 'Batch' && this.isAddedMultipleRowsByMethod && (this.parent.editSettings.newRowPosition === 'Above' || this.parent.editSettings.newRowPosition === 'Below')) {
|
|
13996
|
+
index = this.multipleRowIndex;
|
|
13997
|
+
this.selectedIndex = this.multipleRowIndex;
|
|
13998
|
+
const batchAddedRecords = this.updatedRecords.addedRecords;
|
|
13999
|
+
let newlyAddedRecord;
|
|
14000
|
+
if (batchAddedRecords.length) {
|
|
14001
|
+
for (let i = 0; i < batchAddedRecords.length; i++) {
|
|
14002
|
+
if (isNullOrUndefined(batchAddedRecords[parseInt(i.toString(), 10)].uniqueID)) {
|
|
14003
|
+
newlyAddedRecord = batchAddedRecords[parseInt(i.toString(), 10)];
|
|
14004
|
+
}
|
|
14005
|
+
const args = {
|
|
14006
|
+
action: 'add',
|
|
14007
|
+
data: newlyAddedRecord,
|
|
14008
|
+
index: index,
|
|
14009
|
+
seletedRow: 0
|
|
14010
|
+
};
|
|
14011
|
+
this.beginAddEdit(args);
|
|
14012
|
+
this.batchEditModule['batchAddRowRecord'].push(this.batchEditModule['addRowRecord']);
|
|
14013
|
+
this.batchEditModule['batchAddedRecords'].push(args['data']);
|
|
14014
|
+
}
|
|
14015
|
+
}
|
|
14016
|
+
}
|
|
13329
14017
|
}
|
|
13330
14018
|
// private beforeDataBound(args: BeforeDataBoundArgs): void {
|
|
13331
14019
|
// if (this.parent.grid.isEdit && this.parent.dataSource instanceof DataManager &&
|
|
@@ -13346,6 +14034,9 @@ class Edit {
|
|
|
13346
14034
|
// }
|
|
13347
14035
|
// }
|
|
13348
14036
|
beginEdit(args) {
|
|
14037
|
+
if (this.parent.flatData.length === 0 && !isNullOrUndefined(this.addRowRecord)) {
|
|
14038
|
+
this.addRowRecord = undefined;
|
|
14039
|
+
}
|
|
13349
14040
|
if (args.requestType === 'refresh' && this.isOnBatch) {
|
|
13350
14041
|
args.cancel = true;
|
|
13351
14042
|
return;
|
|
@@ -13607,7 +14298,35 @@ class Edit {
|
|
|
13607
14298
|
if (isNullOrUndefined(index)) {
|
|
13608
14299
|
this.isIndexUndefined = true;
|
|
13609
14300
|
}
|
|
13610
|
-
if (!
|
|
14301
|
+
if (!isNullOrUndefined(data) && Array.isArray(data)) {
|
|
14302
|
+
let addRecords = [];
|
|
14303
|
+
const previousEditMode = this.parent.editSettings.mode;
|
|
14304
|
+
const previousGridEditMode = this.parent.grid.editSettings.mode;
|
|
14305
|
+
if (!this.isSelfReference && !isNullOrUndefined(data) && Object.hasOwnProperty.call(data, this.parent.childMapping)) {
|
|
14306
|
+
addRecords.push(data);
|
|
14307
|
+
}
|
|
14308
|
+
else if (Array.isArray(data)) {
|
|
14309
|
+
addRecords = data;
|
|
14310
|
+
}
|
|
14311
|
+
this.parent.setProperties({ editSettings: { mode: 'Batch' } }, true);
|
|
14312
|
+
this.parent.grid.setProperties({ editSettings: { mode: 'Batch' } }, true);
|
|
14313
|
+
if (!isNullOrUndefined(position)) {
|
|
14314
|
+
this.parent.setProperties({ editSettings: { newRowPosition: position } }, true);
|
|
14315
|
+
}
|
|
14316
|
+
this.updatedRecords = { addedRecords: addRecords, changedRecords: [], deletedRecords: [] };
|
|
14317
|
+
if ((position === 'Above' || position === 'Below') && this.isSelfReference) {
|
|
14318
|
+
this.isAddedMultipleRowsByMethod = true;
|
|
14319
|
+
this.multipleRowIndex = index;
|
|
14320
|
+
this.addRowIndex = index;
|
|
14321
|
+
this.parent.notify(batchAdd, { updatedRecords: this.updatedRecords, index: index });
|
|
14322
|
+
}
|
|
14323
|
+
const updatedRecords = this.updatedRecords;
|
|
14324
|
+
this.parent.notify(batchSave, { updatedRecords, index });
|
|
14325
|
+
this.parent.setProperties({ editSettings: { mode: previousEditMode } }, true);
|
|
14326
|
+
this.parent.grid.setProperties({ editSettings: { mode: previousGridEditMode } }, true);
|
|
14327
|
+
this.parent.refresh();
|
|
14328
|
+
}
|
|
14329
|
+
else if (!this.isSelfReference && !isNullOrUndefined(data) && Object.hasOwnProperty.call(data, this.parent.childMapping)) {
|
|
13611
14330
|
const addRecords = [];
|
|
13612
14331
|
const previousEditMode = this.parent.editSettings.mode;
|
|
13613
14332
|
const previousGridEditMode = this.parent.grid.editSettings.mode;
|
|
@@ -13617,7 +14336,8 @@ class Edit {
|
|
|
13617
14336
|
if (!isNullOrUndefined(position)) {
|
|
13618
14337
|
this.parent.setProperties({ editSettings: { newRowPosition: position } }, true);
|
|
13619
14338
|
}
|
|
13620
|
-
|
|
14339
|
+
this.updatedRecords = { addedRecords: addRecords, changedRecords: [], deletedRecords: [] };
|
|
14340
|
+
const updatedRecords = this.updatedRecords;
|
|
13621
14341
|
this.parent.notify(batchSave, { updatedRecords, index });
|
|
13622
14342
|
this.parent.setProperties({ editSettings: { mode: previousEditMode } }, true);
|
|
13623
14343
|
this.parent.grid.setProperties({ editSettings: { mode: previousGridEditMode } }, true);
|
|
@@ -14097,6 +14817,9 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
|
|
|
14097
14817
|
super.renderTable();
|
|
14098
14818
|
if (!(this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.url !== undefined
|
|
14099
14819
|
&& this.parent.dataSource.dataSource.offline && this.parent.dataSource.dataSource.url !== '') || !isCountRequired(this.parent)) {
|
|
14820
|
+
if (this.observers) {
|
|
14821
|
+
this.observers.disconnect();
|
|
14822
|
+
}
|
|
14100
14823
|
getValue('observer', this).options.debounceEvent = false;
|
|
14101
14824
|
this.observers = new TreeInterSectionObserver(getValue('observer', this).element, getValue('observer', this).options);
|
|
14102
14825
|
this.contents = this.getPanel().firstChild;
|
|
@@ -14811,6 +15534,9 @@ class VirtualTreeContentRenderer extends VirtualContentRenderer {
|
|
|
14811
15534
|
this.parent.off('refresh-virtual-editform-cells', this.refreshCell);
|
|
14812
15535
|
this.parent.off('virtaul-cell-focus', this.cellFocus);
|
|
14813
15536
|
this.parent.off('virtual-scroll-edit', this.restoreEditState);
|
|
15537
|
+
if (this.observers) {
|
|
15538
|
+
this.observers.disconnect();
|
|
15539
|
+
}
|
|
14814
15540
|
}
|
|
14815
15541
|
}
|
|
14816
15542
|
class TreeInterSectionObserver extends InterSectionObserver {
|
|
@@ -14833,12 +15559,28 @@ class TreeInterSectionObserver extends InterSectionObserver {
|
|
|
14833
15559
|
observes(callback, onEnterCallback, instance) {
|
|
14834
15560
|
const containerRect = 'containerRect';
|
|
14835
15561
|
super[`${containerRect}`] = getValue('options', this).container.getBoundingClientRect();
|
|
14836
|
-
|
|
15562
|
+
this.containerEl = getValue('options', this).container;
|
|
15563
|
+
this.containerScrollHandler = this.virtualScrollHandlers(callback, onEnterCallback, instance);
|
|
15564
|
+
EventHandler.add(this.containerEl, 'scroll', this.containerScrollHandler, this);
|
|
14837
15565
|
if (getValue('options', this).movableContainer) {
|
|
14838
15566
|
const movableContainerRect = 'movableContainerRect';
|
|
14839
15567
|
super[`${movableContainerRect}`] = getValue('options', this).movableContainer.getBoundingClientRect();
|
|
14840
|
-
|
|
15568
|
+
this.movableContainerEl = getValue('options', this).movableContainer;
|
|
15569
|
+
this.movableScrollHandler = this.virtualScrollHandlers(callback, onEnterCallback, instance);
|
|
15570
|
+
EventHandler.add(this.movableContainerEl, 'scroll', this.movableScrollHandler, this);
|
|
15571
|
+
}
|
|
15572
|
+
}
|
|
15573
|
+
disconnect() {
|
|
15574
|
+
if (this.containerEl && this.containerScrollHandler) {
|
|
15575
|
+
EventHandler.remove(this.containerEl, 'scroll', this.containerScrollHandler);
|
|
15576
|
+
this.containerScrollHandler = null;
|
|
15577
|
+
}
|
|
15578
|
+
if (this.movableContainerEl && this.movableScrollHandler) {
|
|
15579
|
+
EventHandler.remove(this.movableContainerEl, 'scroll', this.movableScrollHandler);
|
|
15580
|
+
this.movableScrollHandler = null;
|
|
14841
15581
|
}
|
|
15582
|
+
this.containerEl = null;
|
|
15583
|
+
this.movableContainerEl = null;
|
|
14842
15584
|
}
|
|
14843
15585
|
/**
|
|
14844
15586
|
* Clears the last known position.
|
|
@@ -15046,9 +15788,12 @@ class VirtualScroll {
|
|
|
15046
15788
|
const dm = new DataManager(pageingDetails.result);
|
|
15047
15789
|
const expanded = new Predicate$1('expanded', 'notequal', null).or('expanded', 'notequal', undefined);
|
|
15048
15790
|
const parents = dm.executeLocal(new Query().where(expanded));
|
|
15049
|
-
const
|
|
15050
|
-
|
|
15051
|
-
|
|
15791
|
+
const isFiltering = pageingDetails.actionArgs.requestType === 'filtering';
|
|
15792
|
+
const isFlatHierarchy = this.parent.filterSettings.hierarchyMode === 'Child' ||
|
|
15793
|
+
this.parent.filterSettings.hierarchyMode === 'None';
|
|
15794
|
+
const visualData = isFiltering && isFlatHierarchy
|
|
15795
|
+
? parents
|
|
15796
|
+
: parents.filter((e) => getExpandStatus(this.parent, e));
|
|
15052
15797
|
this.visualData = visualData;
|
|
15053
15798
|
pageingDetails.count = visualData.length;
|
|
15054
15799
|
this.parent.grid.notify(dataListener, { data: visualData });
|
|
@@ -15279,7 +16024,7 @@ class Freeze {
|
|
|
15279
16024
|
}
|
|
15280
16025
|
const queryselector = args.action === 'e-childrow-hidden' ? '.e-treecolumn-container .e-treegridcollapse'
|
|
15281
16026
|
: '.e-treecolumn-container .e-treegridexpand';
|
|
15282
|
-
if (frozenrows[row.
|
|
16027
|
+
if (frozenrows[parseInt(row.getAttribute('aria-rowindex'), 10) - 1].querySelector(queryselector)) {
|
|
15283
16028
|
const cRow = [];
|
|
15284
16029
|
for (let i = 0; i < movableRows.length; i++) {
|
|
15285
16030
|
if (movableRows[parseInt(i.toString(), 10)].querySelector('.e-gridrowindex' + rData.index + 'level' + (rData.level + 1))) {
|