Skip to content

Commit dbb2f4f

Browse files
TreeView: Prevent event duplication when items change with selectAll (T1314209) (#31821)
1 parent aaad0fe commit dbb2f4f

File tree

3 files changed

+313
-13
lines changed

3 files changed

+313
-13
lines changed

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

Lines changed: 26 additions & 5 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/index';
79
import messageLocalization from '@js/common/core/localization/message';
@@ -46,22 +48,22 @@ const CUSTOM_EXPANDER_ICON_ITEM_CONTAINER_CLASS = `${WIDGET_CLASS}-custom-expand
4648
const ITEM_WITHOUT_CHECKBOX_CLASS = `${ITEM_CLASS}-without-checkbox`;
4749
const ITEM_DATA_KEY = `${ITEM_CLASS}-data`;
4850

49-
const TOGGLE_ITEM_VISIBILITY_CLASS = `${WIDGET_CLASS}-toggle-item-visibility`;
51+
export const TOGGLE_ITEM_VISIBILITY_CLASS = `${WIDGET_CLASS}-toggle-item-visibility`;
5052
const CUSTOM_COLLAPSE_ICON_CLASS = `${WIDGET_CLASS}-custom-collapse-icon`;
5153
const CUSTOM_EXPAND_ICON_CLASS = `${WIDGET_CLASS}-custom-expand-icon`;
5254

5355
const LOAD_INDICATOR_CLASS = `${WIDGET_CLASS}-loadindicator`;
5456
const LOAD_INDICATOR_WRAPPER_CLASS = `${WIDGET_CLASS}-loadindicator-wrapper`;
5557
const TOGGLE_ITEM_VISIBILITY_OPENED_CLASS = `${WIDGET_CLASS}-toggle-item-visibility-opened`;
56-
const SELECT_ALL_ITEM_CLASS = `${WIDGET_CLASS}-select-all-item`;
58+
export const SELECT_ALL_ITEM_CLASS = `${WIDGET_CLASS}-select-all-item`;
5759

5860
const INVISIBLE_STATE_CLASS = 'dx-state-invisible';
5961
const DISABLED_STATE_CLASS = 'dx-state-disabled';
6062
const SELECTED_ITEM_CLASS = 'dx-state-selected';
6163
const EXPAND_EVENT_NAMESPACE = 'dxTreeView_expand';
6264
const DATA_ITEM_ID = 'data-item-id';
6365
const ITEM_URL_CLASS = 'dx-item-url';
64-
const CHECK_BOX_CLASS = 'dx-checkbox';
66+
export const CHECK_BOX_CLASS = 'dx-checkbox';
6567
const CHECK_BOX_ICON_CLASS = 'dx-checkbox-icon';
6668
const ROOT_NODE_CLASS = `${WIDGET_CLASS}-root-node`;
6769
export const EXPANDER_ICON_STUB_CLASS = `${WIDGET_CLASS}-expander-icon-stub`;
@@ -934,7 +936,23 @@ class TreeViewBase extends HierarchicalCollectionWidget<TreeViewBaseProperties>
934936
eventsEngine.off(itemsContainer, `.${EXPAND_EVENT_NAMESPACE}`, this._itemSelector());
935937
}
936938

937-
_getEventNameByOption(name) {
939+
_detachHoldEvent(itemsContainer: dxElementWrapper): void {
940+
const itemSelector = this._itemSelector();
941+
// @ts-expect-error ts-error
942+
const eventName = addNamespace(holdEvent.name, this.NAME);
943+
944+
eventsEngine.off(itemsContainer, eventName, itemSelector);
945+
}
946+
947+
_detachContextMenuEvent(itemsContainer: dxElementWrapper): void {
948+
const itemSelector = this._itemSelector();
949+
// @ts-expect-error ts-error
950+
const eventName = addNamespace(contextMenuEventName, this.NAME);
951+
952+
eventsEngine.off(itemsContainer, eventName, itemSelector);
953+
}
954+
955+
_getEventNameByOption(name): string {
938956
const event = name === 'click' ? clickEventName : dblclickEvent;
939957
return addNamespace(event, EXPAND_EVENT_NAMESPACE);
940958
}
@@ -1570,7 +1588,10 @@ class TreeViewBase extends HierarchicalCollectionWidget<TreeViewBaseProperties>
15701588

15711589
_detachClickEvent(itemsContainer) {
15721590
const {
1573-
clickEventNamespace, itemSelector, pointerDownEventNamespace, nodeSelector,
1591+
clickEventNamespace,
1592+
pointerDownEventNamespace,
1593+
nodeSelector,
1594+
itemSelector,
15741595
} = this._getItemClickEventData();
15751596

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

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

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,56 @@ const TreeViewSearch = TreeViewBase.inherit(searchBoxMixin).inherit({
9898
return this._getNodeContainer();
9999
}
100100

101-
if (this._scrollable && isSearchMode) {
102-
return $(this._scrollable.content());
101+
if (this.getScrollable() && isSearchMode) {
102+
return $(this.getScrollable().content());
103103
}
104104

105105
return this.callBase();
106106
},
107107

108+
_applyToAllItemContainers(callback: (itemsContainer) => void): void {
109+
if (this.getScrollable()) {
110+
callback($(this.getScrollable().content()));
111+
}
112+
113+
const nodeContainer = this._getNodeContainer();
114+
if (nodeContainer.length) {
115+
callback(nodeContainer);
116+
}
117+
118+
callback(this.$element());
119+
},
120+
121+
_attachClickEvent(): void {
122+
if (this._selectAllEnabled()) {
123+
this._applyToAllItemContainers((itemsContainer) => {
124+
this._detachClickEvent(itemsContainer);
125+
});
126+
}
127+
128+
this.callBase();
129+
},
130+
131+
_attachHoldEvent(): void {
132+
if (this._selectAllEnabled()) {
133+
this._applyToAllItemContainers((itemsContainer) => {
134+
this._detachHoldEvent(itemsContainer);
135+
});
136+
}
137+
138+
this.callBase();
139+
},
140+
141+
_attachContextMenuEvent(): void {
142+
if (this._selectAllEnabled()) {
143+
this._applyToAllItemContainers((itemsContainer) => {
144+
this._detachContextMenuEvent(itemsContainer);
145+
});
146+
}
147+
148+
this.callBase();
149+
},
150+
108151
_addWidgetClass() {
109152
this.$element().addClass(this._widgetClass());
110153
},

0 commit comments

Comments
 (0)