From 45548ad054d3a37b9aae14860bb34f7cad667868 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 28 Jan 2026 09:31:56 +0100 Subject: [PATCH 01/16] fix: fix bug --- .../pivot_grid/data_source/m_data_source.ts | 27 ++++++++++--------- .../pivot_grid/local_store/m_local_store.ts | 5 +++- .../pivot_grid/remote_store/m_remote_store.ts | 4 +++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts index b5b1683bc03f..b5650b2327de 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts @@ -717,9 +717,9 @@ class PivotGridDataSource { values: this.getAreaFields('data'), filters: applyFilters ? this._fields.filter((f) => f !== field - && f.area - && f.filterValues - && f.filterValues.length) + && f.area + && f.filterValues + && f.filterValues.length) : [], skipValues: true, }; @@ -839,8 +839,8 @@ class PivotGridDataSource { } if (field.levels - && dimension !== descriptions.filters - && dimension !== descriptions.values) { + && dimension !== descriptions.filters + && dimension !== descriptions.values) { dimension.push.apply(dimension, field.levels); if (field.filterValues && field.filterValues.length) { descriptions.filters.push(field); @@ -1049,9 +1049,9 @@ class PivotGridDataSource { if (store) { extend(options, descriptions); options.columnExpandedPaths = options.columnExpandedPaths - || this.getExpandedPaths(this._data, options, 'columns', that._lastLoadOptions); + || this.getExpandedPaths(this._data, options, 'columns', that._lastLoadOptions); options.rowExpandedPaths = options.rowExpandedPaths - || this.getExpandedPaths(this._data, options, 'rows', that._lastLoadOptions); + || this.getExpandedPaths(this._data, options, 'rows', that._lastLoadOptions); if (paginate) { options.pageSize = this._pageSize; @@ -1076,7 +1076,7 @@ class PivotGridDataSource { storeLoadOptions = storeLoadOptions .filter((options) => !(options.rows.length && options.rowTake === 0) - && !(options.columns.length && options.columnTake === 0)); + && !(options.columns.length && options.columnTake === 0)); if (!storeLoadOptions.length) { that._update(deferred); @@ -1130,8 +1130,8 @@ class PivotGridDataSource { paginate() { return this._paginate - && this._store - && this._store.supportPaging(); + && this._store + && this._store.supportPaging(); } isEmpty() { @@ -1160,8 +1160,8 @@ class PivotGridDataSource { that._sort(descriptions, loadedData); !that.isEmpty() - && isRunningTotalUsed(dataFields) - && summaryUtils.applyRunningTotal(descriptions, loadedData); + && isRunningTotalUsed(dataFields) + && summaryUtils.applyRunningTotal(descriptions, loadedData); that._data = loadedData; deferred !== false && when(deferred).done(() => { @@ -1405,6 +1405,9 @@ class PivotGridDataSource { if (delayedLoadTask) { delayedLoadTask.abort(); } + + that._store?.dispose(); + this._isDisposed = true; } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts index 174166bf6091..089fcf6da4c0 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts @@ -2,7 +2,6 @@ import ArrayStore from '@js/common/data/array_store'; import { CustomStore } from '@js/common/data/custom_store'; import { DataSource } from '@js/common/data/data_source/data_source'; import dataQuery from '@js/common/data/query'; -// eslint-disable-next-line import/extensions import { aggregators } from '@js/common/data/utils'; import Class from '@js/core/class'; import { noop } from '@js/core/utils/common'; @@ -585,6 +584,10 @@ const LocalStore = Class.inherit((function () { return drillDownItems; }, + + dispose() { + this._dataSource?.dispose(); + }, }; })()).include(storeDrillDownMixin); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts index 3412120c14f2..2f9ea5648be5 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts @@ -662,6 +662,10 @@ class RemoteStore { }, }); } + + dispose() { + this._dataSource?.dispose(); + } } export default { RemoteStore }; From 4a2982324b55d863197058da26bbd9567f3ae921 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 28 Jan 2026 09:44:56 +0100 Subject: [PATCH 02/16] test: add test for bug --- .../dataSource_bundled.tests.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js index 2b4ad041c12d..0a6f30361ae4 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js @@ -6917,6 +6917,29 @@ QUnit.module('Stores', () => { }); }); + QUnit.test('PivotGridDataSource dispose disposes LocalStore', function(assert) { + const dataSource = new PivotGridDataSource({ + store: window.orders + }); + const store = dataSource.store(); + + dataSource.dispose(); + + assert.ok(store._dataSource._disposed, 'LocalStore internal DataSource is disposed'); + }); + + QUnit.test('PivotGridDataSource dispose disposes RemoteStore', function(assert) { + const dataSource = new PivotGridDataSource({ + remoteOperations: true, + store: window.orders + }); + const store = dataSource.store(); + + dataSource.dispose(); + + assert.ok(store._dataSource._disposed, 'RemoteStore internal DataSource is disposed'); + }); + }); From 8c3e6103ac6a511274bee73c9feaefa309e77dcd Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 28 Jan 2026 11:10:18 +0100 Subject: [PATCH 03/16] fix: fix bug --- .../__internal/grids/pivot_grid/data_source/m_data_source.ts | 4 +++- .../__internal/grids/pivot_grid/local_store/m_local_store.ts | 4 +++- .../grids/pivot_grid/remote_store/m_remote_store.ts | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts index b5650b2327de..af828290f96f 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts @@ -1406,7 +1406,9 @@ class PivotGridDataSource { delayedLoadTask.abort(); } - that._store?.dispose(); + if (that._store) { + that._store.dispose(); + } this._isDisposed = true; } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts index 089fcf6da4c0..e71bf33cf091 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts @@ -586,7 +586,9 @@ const LocalStore = Class.inherit((function () { }, dispose() { - this._dataSource?.dispose(); + if (this._dataSource) { + this._dataSource.dispose(); + } }, }; })()).include(storeDrillDownMixin); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts index 2f9ea5648be5..03441a591f19 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts @@ -664,7 +664,9 @@ class RemoteStore { } dispose() { - this._dataSource?.dispose(); + if (this._dataSource) { + this._dataSource.dispose(); + } } } From 0235dc83e8bb11e75a274a3856e14903011b747f Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 28 Jan 2026 13:27:38 +0100 Subject: [PATCH 04/16] Revert "fix: fix bug" This reverts commit 8c3e6103ac6a511274bee73c9feaefa309e77dcd. --- .../__internal/grids/pivot_grid/data_source/m_data_source.ts | 4 +--- .../__internal/grids/pivot_grid/local_store/m_local_store.ts | 4 +--- .../grids/pivot_grid/remote_store/m_remote_store.ts | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts index af828290f96f..b5650b2327de 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts @@ -1406,9 +1406,7 @@ class PivotGridDataSource { delayedLoadTask.abort(); } - if (that._store) { - that._store.dispose(); - } + that._store?.dispose(); this._isDisposed = true; } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts index e71bf33cf091..089fcf6da4c0 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts @@ -586,9 +586,7 @@ const LocalStore = Class.inherit((function () { }, dispose() { - if (this._dataSource) { - this._dataSource.dispose(); - } + this._dataSource?.dispose(); }, }; })()).include(storeDrillDownMixin); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts index 03441a591f19..2f9ea5648be5 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts @@ -664,9 +664,7 @@ class RemoteStore { } dispose() { - if (this._dataSource) { - this._dataSource.dispose(); - } + this._dataSource?.dispose(); } } From 8875a5c01c222ccc7d43aeb64ed500124863ca70 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 28 Jan 2026 13:28:15 +0100 Subject: [PATCH 05/16] fix: fix bug --- .../js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts index 42245f38de34..384eaee528dc 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts @@ -1159,6 +1159,9 @@ class XmlaStore { return true; } + dispose() { + } + getDrillDownItems(options, params) { // @ts-expect-error const result = new Deferred(); From c23c38d7c54de792dfb8adfa6e4f4ef42a282855 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 13:38:52 +0100 Subject: [PATCH 06/16] Revert "fix: fix bug" This reverts commit 8875a5c01c222ccc7d43aeb64ed500124863ca70. --- .../js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts index 384eaee528dc..42245f38de34 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/xmla_store/m_xmla_store.ts @@ -1159,9 +1159,6 @@ class XmlaStore { return true; } - dispose() { - } - getDrillDownItems(options, params) { // @ts-expect-error const result = new Deferred(); From 973a00ccaef73a426d3b561db2a5ff9989ec1e92 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 13:38:52 +0100 Subject: [PATCH 07/16] Revert "fix: fix bug" This reverts commit 45548ad054d3a37b9aae14860bb34f7cad667868. --- .../pivot_grid/data_source/m_data_source.ts | 27 +++++++++---------- .../pivot_grid/local_store/m_local_store.ts | 5 +--- .../pivot_grid/remote_store/m_remote_store.ts | 4 --- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts index b5650b2327de..b5b1683bc03f 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_source/m_data_source.ts @@ -717,9 +717,9 @@ class PivotGridDataSource { values: this.getAreaFields('data'), filters: applyFilters ? this._fields.filter((f) => f !== field - && f.area - && f.filterValues - && f.filterValues.length) + && f.area + && f.filterValues + && f.filterValues.length) : [], skipValues: true, }; @@ -839,8 +839,8 @@ class PivotGridDataSource { } if (field.levels - && dimension !== descriptions.filters - && dimension !== descriptions.values) { + && dimension !== descriptions.filters + && dimension !== descriptions.values) { dimension.push.apply(dimension, field.levels); if (field.filterValues && field.filterValues.length) { descriptions.filters.push(field); @@ -1049,9 +1049,9 @@ class PivotGridDataSource { if (store) { extend(options, descriptions); options.columnExpandedPaths = options.columnExpandedPaths - || this.getExpandedPaths(this._data, options, 'columns', that._lastLoadOptions); + || this.getExpandedPaths(this._data, options, 'columns', that._lastLoadOptions); options.rowExpandedPaths = options.rowExpandedPaths - || this.getExpandedPaths(this._data, options, 'rows', that._lastLoadOptions); + || this.getExpandedPaths(this._data, options, 'rows', that._lastLoadOptions); if (paginate) { options.pageSize = this._pageSize; @@ -1076,7 +1076,7 @@ class PivotGridDataSource { storeLoadOptions = storeLoadOptions .filter((options) => !(options.rows.length && options.rowTake === 0) - && !(options.columns.length && options.columnTake === 0)); + && !(options.columns.length && options.columnTake === 0)); if (!storeLoadOptions.length) { that._update(deferred); @@ -1130,8 +1130,8 @@ class PivotGridDataSource { paginate() { return this._paginate - && this._store - && this._store.supportPaging(); + && this._store + && this._store.supportPaging(); } isEmpty() { @@ -1160,8 +1160,8 @@ class PivotGridDataSource { that._sort(descriptions, loadedData); !that.isEmpty() - && isRunningTotalUsed(dataFields) - && summaryUtils.applyRunningTotal(descriptions, loadedData); + && isRunningTotalUsed(dataFields) + && summaryUtils.applyRunningTotal(descriptions, loadedData); that._data = loadedData; deferred !== false && when(deferred).done(() => { @@ -1405,9 +1405,6 @@ class PivotGridDataSource { if (delayedLoadTask) { delayedLoadTask.abort(); } - - that._store?.dispose(); - this._isDisposed = true; } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts index 089fcf6da4c0..174166bf6091 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/local_store/m_local_store.ts @@ -2,6 +2,7 @@ import ArrayStore from '@js/common/data/array_store'; import { CustomStore } from '@js/common/data/custom_store'; import { DataSource } from '@js/common/data/data_source/data_source'; import dataQuery from '@js/common/data/query'; +// eslint-disable-next-line import/extensions import { aggregators } from '@js/common/data/utils'; import Class from '@js/core/class'; import { noop } from '@js/core/utils/common'; @@ -584,10 +585,6 @@ const LocalStore = Class.inherit((function () { return drillDownItems; }, - - dispose() { - this._dataSource?.dispose(); - }, }; })()).include(storeDrillDownMixin); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts index 2f9ea5648be5..3412120c14f2 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/remote_store/m_remote_store.ts @@ -662,10 +662,6 @@ class RemoteStore { }, }); } - - dispose() { - this._dataSource?.dispose(); - } } export default { RemoteStore }; From d3833a2f35346f8994bee797799878e7b1e43112 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 13:40:13 +0100 Subject: [PATCH 08/16] Revert "test: add test for bug" This reverts commit 4a2982324b55d863197058da26bbd9567f3ae921. --- .../dataSource_bundled.tests.js | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js index 0a6f30361ae4..2b4ad041c12d 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataSource_bundled.tests.js @@ -6917,29 +6917,6 @@ QUnit.module('Stores', () => { }); }); - QUnit.test('PivotGridDataSource dispose disposes LocalStore', function(assert) { - const dataSource = new PivotGridDataSource({ - store: window.orders - }); - const store = dataSource.store(); - - dataSource.dispose(); - - assert.ok(store._dataSource._disposed, 'LocalStore internal DataSource is disposed'); - }); - - QUnit.test('PivotGridDataSource dispose disposes RemoteStore', function(assert) { - const dataSource = new PivotGridDataSource({ - remoteOperations: true, - store: window.orders - }); - const store = dataSource.store(); - - dataSource.dispose(); - - assert.ok(store._dataSource._disposed, 'RemoteStore internal DataSource is disposed'); - }); - }); From 9aea4601f946c279f82670406356fea52183d3c0 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 11:55:20 +0100 Subject: [PATCH 09/16] fix: broken pivot grid but without memory leak --- .../__internal/grids/pivot_grid/m_widget.ts | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index a8551242092a..2f3ba13bea79 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -29,7 +29,7 @@ import DataAreaImport from './data_area/m_data_area'; import DataControllerImport from './data_controller/m_data_controller'; import { ExportController } from './export/m_export'; import { FieldChooser } from './field_chooser/m_field_chooser'; -import { FieldChooserBase } from './field_chooser/m_field_chooser_base'; +// import { FieldChooserBase } from './field_chooser/m_field_chooser_base'; import { FieldsArea } from './fields_area/m_fields_area'; import HeadersArea from './headers_area/m_headers_area'; import { findField, mergeArraysByMaxValue, setFieldProperty } from './m_widget_utils'; @@ -645,19 +645,22 @@ class PivotGrid extends Widget { }, }; - if (that.getFieldChooserPopup()) { - that._fieldChooserPopup.option(popupOptions); - that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); - } else { - that._fieldChooserPopup = that._createComponent( - $(DIV) - .addClass(FIELD_CHOOSER_POPUP_CLASS) - .appendTo(container), - Popup, - // @ts-expect-error ts-error - popupOptions, - ); + if (that._fieldChooserPopup) { + if (that._fieldChooserPopup.option('visible')) { + that._fieldChooserPopup.hide(); + } + that._fieldChooserPopup.dispose(); + that._fieldChooserPopup = null; } + + that._fieldChooserPopup = that._createComponent( + $(DIV) + .addClass(FIELD_CHOOSER_POPUP_CLASS) + .appendTo(container), + Popup, + // @ts-expect-error ts-error + popupOptions, + ); } _renderContextMenu() { @@ -1174,15 +1177,15 @@ class PivotGrid extends Widget { that.$element().addClass(OVERFLOW_HIDDEN_CLASS); - that._createComponent(that.$element(), FieldChooserBase, { - dataSource: that.getDataSource(), - encodeHtml: that.option('encodeHtml'), - allowFieldDragging: that.option('fieldPanel.allowFieldDragging'), - headerFilter: that.option('headerFilter'), - visible: that.option('visible'), - // @ts-expect-error ts-error - remoteSort: that.option('scrolling.mode') === 'virtual', - }); + // that._createComponent(that.$element(), FieldChooserBase, { + // dataSource: that.getDataSource(), + // encodeHtml: that.option('encodeHtml'), + // allowFieldDragging: that.option('fieldPanel.allowFieldDragging'), + // headerFilter: that.option('headerFilter'), + // visible: that.option('visible'), + // // @ts-expect-error ts-error + // remoteSort: that.option('scrolling.mode') === 'virtual', + // }); const dataArea = that._renderDataArea(dataAreaElement); const rowsArea = that._renderRowsArea(rowsAreaElement); @@ -1266,9 +1269,17 @@ class PivotGrid extends Widget { _dispose() { const that = this; clearTimeout(that._hideLoadingTimeoutID); + + if (that._fieldChooserPopup) { + that._fieldChooserPopup.dispose(); + that._fieldChooserPopup = null; + } + super._dispose(); + if (that._dataController) { that._dataController.dispose(); + that._dataController = null; } } From 60f8913c562f08956be9f99ed72aa14bd2e69f98 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 13:35:11 +0100 Subject: [PATCH 10/16] fix: fix field chooser --- .../field_chooser/m_field_chooser.ts | 2 +- .../field_chooser/m_field_chooser_base.ts | 6 ++++ .../__internal/grids/pivot_grid/m_widget.ts | 31 +++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser.ts b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser.ts index 91a449e64ae4..07e01126be7c 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser.ts @@ -143,7 +143,7 @@ export class FieldChooser extends FieldChooserBase { _dispose() { this._disposeDataSource(); - super._dispose.apply(this, arguments); + super._dispose(); } _init() { diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts index f9a98f4830b4..b959a2b8d695 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts @@ -440,6 +440,12 @@ export class FieldChooserBase extends mixinWidget { addWidgetPrefix(className) { return `dx-pivotgrid-${className}`; } + + _dispose() { + this._eventsStrategy.fireEvent('disposing', [{ component: this }]); + this._dataSource = null; + super._dispose(); + } } registerComponent('dxPivotGridFieldChooserBase', FieldChooserBase as any); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index 2f3ba13bea79..01f08cc11e8b 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -29,7 +29,7 @@ import DataAreaImport from './data_area/m_data_area'; import DataControllerImport from './data_controller/m_data_controller'; import { ExportController } from './export/m_export'; import { FieldChooser } from './field_chooser/m_field_chooser'; -// import { FieldChooserBase } from './field_chooser/m_field_chooser_base'; +import { FieldChooserBase } from './field_chooser/m_field_chooser_base'; import { FieldsArea } from './fields_area/m_fields_area'; import HeadersArea from './headers_area/m_headers_area'; import { findField, mergeArraysByMaxValue, setFieldProperty } from './m_widget_utils'; @@ -135,6 +135,8 @@ class PivotGrid extends Widget { _fieldChooser: any; + _fieldChooserBase: any; + _columnsArea: any; _rowsArea: any; @@ -408,6 +410,10 @@ class PivotGrid extends Widget { case 'allowSortingBySummary': case 'scrolling': case 'stateStoring': + if (that._fieldChooserBase) { + that._fieldChooserBase._dispose(); + that._fieldChooserBase = null; + } that._initDataController(); that.getFieldChooserPopup().hide(); that._renderFieldChooser(); @@ -1177,15 +1183,15 @@ class PivotGrid extends Widget { that.$element().addClass(OVERFLOW_HIDDEN_CLASS); - // that._createComponent(that.$element(), FieldChooserBase, { - // dataSource: that.getDataSource(), - // encodeHtml: that.option('encodeHtml'), - // allowFieldDragging: that.option('fieldPanel.allowFieldDragging'), - // headerFilter: that.option('headerFilter'), - // visible: that.option('visible'), - // // @ts-expect-error ts-error - // remoteSort: that.option('scrolling.mode') === 'virtual', - // }); + that._fieldChooserBase = that._createComponent(that.$element(), FieldChooserBase, { + dataSource: that.getDataSource(), + encodeHtml: that.option('encodeHtml'), + allowFieldDragging: that.option('fieldPanel.allowFieldDragging'), + headerFilter: that.option('headerFilter'), + visible: that.option('visible'), + // @ts-expect-error ts-error + remoteSort: that.option('scrolling.mode') === 'virtual', + }); const dataArea = that._renderDataArea(dataAreaElement); const rowsArea = that._renderRowsArea(rowsAreaElement); @@ -1275,6 +1281,11 @@ class PivotGrid extends Widget { that._fieldChooserPopup = null; } + if (that._fieldChooserBase) { + that._fieldChooserBase._dispose(); + that._fieldChooserBase = null; + } + super._dispose(); if (that._dataController) { From e60ae9a3e386e4df9e3cd5088ce5babc45337be4 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Tue, 10 Feb 2026 15:30:45 +0100 Subject: [PATCH 11/16] fix: fix test --- .../__internal/grids/pivot_grid/m_widget.ts | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index 01f08cc11e8b..7695a59585d1 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -415,8 +415,11 @@ class PivotGrid extends Widget { that._fieldChooserBase = null; } that._initDataController(); - that.getFieldChooserPopup().hide(); - that._renderFieldChooser(); + that.getFieldChooserPopup().hide().then(() => { + that.getFieldChooserPopup().dispose(); + that._fieldChooserPopup = null; + that._renderFieldChooser(); + }); that._invalidate(); break; case 'texts': @@ -651,22 +654,20 @@ class PivotGrid extends Widget { }, }; - if (that._fieldChooserPopup) { - if (that._fieldChooserPopup.option('visible')) { - that._fieldChooserPopup.hide(); - } - that._fieldChooserPopup.dispose(); - that._fieldChooserPopup = null; + if (that.getFieldChooserPopup()) { + that._fieldChooserPopup.option(popupOptions); + that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); + } else { + that._fieldChooserPopup = that._createComponent( + $(DIV) + .addClass(FIELD_CHOOSER_POPUP_CLASS) + .appendTo(container), + Popup, + // @ts-expect-error ts-error + popupOptions, + ); + that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); } - - that._fieldChooserPopup = that._createComponent( - $(DIV) - .addClass(FIELD_CHOOSER_POPUP_CLASS) - .appendTo(container), - Popup, - // @ts-expect-error ts-error - popupOptions, - ); } _renderContextMenu() { @@ -1286,12 +1287,12 @@ class PivotGrid extends Widget { that._fieldChooserBase = null; } - super._dispose(); - if (that._dataController) { that._dataController.dispose(); that._dataController = null; } + + super._dispose(); } _tableElement() { From 41b4181c4da57df95946d42c57ef5bc5d0272019 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 11 Feb 2026 09:28:03 +0100 Subject: [PATCH 12/16] fix: try to fix test --- .../devextreme/js/__internal/grids/pivot_grid/m_widget.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index 7695a59585d1..93d1fdecf5d6 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -416,8 +416,7 @@ class PivotGrid extends Widget { } that._initDataController(); that.getFieldChooserPopup().hide().then(() => { - that.getFieldChooserPopup().dispose(); - that._fieldChooserPopup = null; + this.getFieldChooserPopup().dispose(); that._renderFieldChooser(); }); that._invalidate(); @@ -666,7 +665,6 @@ class PivotGrid extends Widget { // @ts-expect-error ts-error popupOptions, ); - that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); } } From 0d69b8f1125fee20844fc8caa41fc4e15712fc12 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 11 Feb 2026 12:55:27 +0100 Subject: [PATCH 13/16] Revert "fix: try to fix test" This reverts commit 41b4181c4da57df95946d42c57ef5bc5d0272019. --- .../devextreme/js/__internal/grids/pivot_grid/m_widget.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index 93d1fdecf5d6..7695a59585d1 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -416,7 +416,8 @@ class PivotGrid extends Widget { } that._initDataController(); that.getFieldChooserPopup().hide().then(() => { - this.getFieldChooserPopup().dispose(); + that.getFieldChooserPopup().dispose(); + that._fieldChooserPopup = null; that._renderFieldChooser(); }); that._invalidate(); @@ -665,6 +666,7 @@ class PivotGrid extends Widget { // @ts-expect-error ts-error popupOptions, ); + that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); } } From 17c71a3733fd45a90d7aded0620a874e9ada96de Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 11 Feb 2026 12:57:43 +0100 Subject: [PATCH 14/16] Revert "fix: broken pivot grid but without memory leak" This reverts commit 9aea4601 --- .../js/__internal/grids/pivot_grid/m_widget.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index 7695a59585d1..a27355a4b73c 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -415,11 +415,8 @@ class PivotGrid extends Widget { that._fieldChooserBase = null; } that._initDataController(); - that.getFieldChooserPopup().hide().then(() => { - that.getFieldChooserPopup().dispose(); - that._fieldChooserPopup = null; - that._renderFieldChooser(); - }); + that.getFieldChooserPopup().hide(); + that._renderFieldChooser(); that._invalidate(); break; case 'texts': @@ -666,7 +663,6 @@ class PivotGrid extends Widget { // @ts-expect-error ts-error popupOptions, ); - that._fieldChooserPopup.$content().dxPivotGridFieldChooser(fieldChooserComponentOptions); } } @@ -1277,11 +1273,6 @@ class PivotGrid extends Widget { const that = this; clearTimeout(that._hideLoadingTimeoutID); - if (that._fieldChooserPopup) { - that._fieldChooserPopup.dispose(); - that._fieldChooserPopup = null; - } - if (that._fieldChooserBase) { that._fieldChooserBase._dispose(); that._fieldChooserBase = null; From d48ef4ef3683062b93e8a1be4668e7e005fd37a9 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 11 Feb 2026 14:51:41 +0100 Subject: [PATCH 15/16] test: add test --- .../pivotGrid.tests.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/pivotGrid.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/pivotGrid.tests.js index a70a1c2138e6..c4f895af9aaf 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/pivotGrid.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/pivotGrid.tests.js @@ -1044,6 +1044,24 @@ QUnit.module('dxPivotGrid', { }); + QUnit.test('T1317109: fieldChooser disposes on dataSource change', function(assert) { + const pivotGrid = createPivotGrid({ + dataSource: { + rows: [], + columns: [], + values: [] + } + }); + + const disposeSpy = sinon.spy(pivotGrid._fieldChooserBase, '_dispose'); + + pivotGrid.option('dataSource', this.testOptions.dataSource); + + this.clock.tick(500); + + assert.ok(disposeSpy.calledOnce, '_dispose was called once on dataSource change'); + }); + QUnit.test('not show field chooser popup on description area click when fieldChooser disabled', function(assert) { createPivotGrid({ fieldChooser: { From 17ac4c68c3b43f41c553217465be4902958d7791 Mon Sep 17 00:00:00 2001 From: Sergio Bur Date: Wed, 11 Feb 2026 19:32:12 +0100 Subject: [PATCH 16/16] fix: fixes after review --- .../grids/pivot_grid/field_chooser/m_field_chooser_base.ts | 6 ------ .../devextreme/js/__internal/grids/pivot_grid/m_widget.ts | 3 --- 2 files changed, 9 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts index b959a2b8d695..f9a98f4830b4 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/field_chooser/m_field_chooser_base.ts @@ -440,12 +440,6 @@ export class FieldChooserBase extends mixinWidget { addWidgetPrefix(className) { return `dx-pivotgrid-${className}`; } - - _dispose() { - this._eventsStrategy.fireEvent('disposing', [{ component: this }]); - this._dataSource = null; - super._dispose(); - } } registerComponent('dxPivotGridFieldChooserBase', FieldChooserBase as any); diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts index a27355a4b73c..c1b08371354e 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -412,7 +412,6 @@ class PivotGrid extends Widget { case 'stateStoring': if (that._fieldChooserBase) { that._fieldChooserBase._dispose(); - that._fieldChooserBase = null; } that._initDataController(); that.getFieldChooserPopup().hide(); @@ -1275,12 +1274,10 @@ class PivotGrid extends Widget { if (that._fieldChooserBase) { that._fieldChooserBase._dispose(); - that._fieldChooserBase = null; } if (that._dataController) { that._dataController.dispose(); - that._dataController = null; } super._dispose();