Skip to content

Commit 84c3f53

Browse files
TreeView: Prevent events duplication when items change at runtime in selectAll mode (T1314209) (DevExpress#31819)
1 parent 1008882 commit 84c3f53

File tree

3 files changed

+312
-12
lines changed

3 files changed

+312
-12
lines changed

packages/devextreme/js/__internal/ui/tree_view/tree_view.base.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { fx } from '@js/common/core/animation';
22
import { name as clickEventName } from '@js/common/core/events/click';
3+
import { name as contextMenuEventName } from '@js/common/core/events/contextmenu';
34
import eventsEngine from '@js/common/core/events/core/events_engine';
45
import { name as dblclickEvent } from '@js/common/core/events/double_click';
6+
import holdEvent from '@js/common/core/events/hold';
57
import pointerEvents from '@js/common/core/events/pointer';
68
import { addNamespace } from '@js/common/core/events/utils';
79
import messageLocalization from '@js/common/core/localization/message';
@@ -63,22 +65,22 @@ const CUSTOM_EXPANDER_ICON_ITEM_CONTAINER_CLASS = `${WIDGET_CLASS}-custom-expand
6365
const ITEM_WITHOUT_CHECKBOX_CLASS = `${ITEM_CLASS}-without-checkbox`;
6466
const ITEM_DATA_KEY = `${ITEM_CLASS}-data`;
6567

66-
const TOGGLE_ITEM_VISIBILITY_CLASS = `${WIDGET_CLASS}-toggle-item-visibility`;
68+
export const TOGGLE_ITEM_VISIBILITY_CLASS = `${WIDGET_CLASS}-toggle-item-visibility`;
6769
const CUSTOM_COLLAPSE_ICON_CLASS = `${WIDGET_CLASS}-custom-collapse-icon`;
6870
const CUSTOM_EXPAND_ICON_CLASS = `${WIDGET_CLASS}-custom-expand-icon`;
6971

7072
const LOAD_INDICATOR_CLASS = `${WIDGET_CLASS}-loadindicator`;
7173
const LOAD_INDICATOR_WRAPPER_CLASS = `${WIDGET_CLASS}-loadindicator-wrapper`;
7274
const TOGGLE_ITEM_VISIBILITY_OPENED_CLASS = `${WIDGET_CLASS}-toggle-item-visibility-opened`;
73-
const SELECT_ALL_ITEM_CLASS = `${WIDGET_CLASS}-select-all-item`;
75+
export const SELECT_ALL_ITEM_CLASS = `${WIDGET_CLASS}-select-all-item`;
7476

7577
const INVISIBLE_STATE_CLASS = 'dx-state-invisible';
7678
const DISABLED_STATE_CLASS = 'dx-state-disabled';
7779
const SELECTED_ITEM_CLASS = 'dx-state-selected';
7880
const EXPAND_EVENT_NAMESPACE = 'dxTreeView_expand';
7981
const DATA_ITEM_ID = 'data-item-id';
8082
const ITEM_URL_CLASS = 'dx-item-url';
81-
const CHECK_BOX_CLASS = 'dx-checkbox';
83+
export const CHECK_BOX_CLASS = 'dx-checkbox';
8284
const CHECK_BOX_ICON_CLASS = 'dx-checkbox-icon';
8385
const ROOT_NODE_CLASS = `${WIDGET_CLASS}-root-node`;
8486
export const EXPANDER_ICON_STUB_CLASS = `${WIDGET_CLASS}-expander-icon-stub`;
@@ -1075,6 +1077,22 @@ class TreeViewBase extends HierarchicalCollectionWidget<TreeViewBaseProperties,
10751077
eventsEngine.off(itemsContainer, `.${EXPAND_EVENT_NAMESPACE}`, this._itemSelector());
10761078
}
10771079

1080+
_detachHoldEvent(itemsContainer: dxElementWrapper): void {
1081+
const itemSelector = this._itemSelector();
1082+
// @ts-expect-error ts-error
1083+
const eventName = addNamespace(holdEvent.name, this.NAME);
1084+
1085+
eventsEngine.off(itemsContainer, eventName, itemSelector);
1086+
}
1087+
1088+
_detachContextMenuEvent(itemsContainer: dxElementWrapper): void {
1089+
const itemSelector = this._itemSelector();
1090+
// @ts-expect-error ts-error
1091+
const eventName = addNamespace(contextMenuEventName, this.NAME);
1092+
1093+
eventsEngine.off(itemsContainer, eventName, itemSelector);
1094+
}
1095+
10781096
_getEventNameByOption(name: TreeViewExpandEvent | undefined): string {
10791097
const event = name === 'click' ? clickEventName : dblclickEvent;
10801098
return addNamespace(event, EXPAND_EVENT_NAMESPACE);
@@ -1817,7 +1835,10 @@ class TreeViewBase extends HierarchicalCollectionWidget<TreeViewBaseProperties,
18171835

18181836
_detachClickEvent(itemsContainer: dxElementWrapper): void {
18191837
const {
1820-
clickEventNamespace, itemSelector, pointerDownEventNamespace, nodeSelector,
1838+
clickEventNamespace,
1839+
pointerDownEventNamespace,
1840+
nodeSelector,
1841+
itemSelector,
18211842
} = this._getItemClickEventData();
18221843

18231844
eventsEngine.off(itemsContainer, clickEventNamespace, itemSelector);

packages/devextreme/js/__internal/ui/tree_view/tree_view.search.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,56 @@ class TreeViewSearch extends TreeViewBase {
195195
return this._getNodeContainer();
196196
}
197197

198-
if (this._scrollable && isSearchMode) {
199-
return $(this._scrollable.content());
198+
if (this.getScrollable() && isSearchMode) {
199+
return $(this.getScrollable().content());
200200
}
201201

202202
return super._itemContainer();
203203
}
204204

205+
_applyToAllItemContainers(callback: (itemsContainer: dxElementWrapper) => void): void {
206+
if (this.getScrollable()) {
207+
callback($(this.getScrollable().content()));
208+
}
209+
210+
const nodeContainer = this._getNodeContainer();
211+
if (nodeContainer.length) {
212+
callback(nodeContainer);
213+
}
214+
215+
callback(this.$element());
216+
}
217+
218+
_attachClickEvent(): void {
219+
if (this._selectAllEnabled()) {
220+
this._applyToAllItemContainers((itemsContainer) => {
221+
this._detachClickEvent(itemsContainer);
222+
});
223+
}
224+
225+
super._attachClickEvent();
226+
}
227+
228+
_attachHoldEvent(): void {
229+
if (this._selectAllEnabled()) {
230+
this._applyToAllItemContainers((itemsContainer) => {
231+
this._detachHoldEvent(itemsContainer);
232+
});
233+
}
234+
235+
super._attachHoldEvent();
236+
}
237+
238+
_attachContextMenuEvent(): void {
239+
if (this._selectAllEnabled()) {
240+
this._applyToAllItemContainers((itemsContainer) => {
241+
this._detachContextMenuEvent(itemsContainer);
242+
});
243+
}
244+
245+
super._attachContextMenuEvent();
246+
}
247+
205248
_addWidgetClass(): void {
206249
this.$element().addClass(this._widgetClass());
207250
}

0 commit comments

Comments
 (0)