From 2b52f35c9e75bdf390e18d9d38831d7223b0c57e Mon Sep 17 00:00:00 2001 From: AlisherAmonulloev Date: Sat, 31 Jan 2026 13:26:17 +0200 Subject: [PATCH 1/2] Create FieldChooserBase only once --- .../__internal/grids/pivot_grid/m_widget.ts | 13 +++++-- .../pivotGrid.tests.js | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+), 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 a8551242092a..c720b0366d37 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -1174,15 +1174,22 @@ class PivotGrid extends Widget { that.$element().addClass(OVERFLOW_HIDDEN_CLASS); - that._createComponent(that.$element(), FieldChooserBase, { - dataSource: that.getDataSource(), + const fieldChooserOptions = { + dataSource: that.option('dataSource'), 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', - }); + }; + + if (isFirstDrawing) { + that._createComponent(that.$element(), FieldChooserBase, fieldChooserOptions); + } else { + // @ts-expect-error dxPivotGridFieldChooserBase is registered as jQuery plugin + that.$element().dxPivotGridFieldChooserBase('instance').option(fieldChooserOptions); + } const dataArea = that._renderDataArea(dataAreaElement); const rowsArea = that._renderRowsArea(rowsAreaElement); 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 47575050dd08..f036c89e9d62 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,43 @@ QUnit.module('dxPivotGrid', { }); + QUnit.test('Reassigning dataSource keeps only one current PivotGridDataSource instance (no stale references)', function(assert) { + const baseOptions = { + store: { type: 'array', data: [] }, + fields: [ + { area: 'row', dataField: 'region' }, + { area: 'column', dataField: 'date' }, + { area: 'data', dataField: 'amount', summaryType: 'sum' } + ] + }; + + const dataSource1 = new PivotGridDataSource(baseOptions); + const dataSource2 = new PivotGridDataSource(baseOptions); + const dataSource3 = new PivotGridDataSource(baseOptions); + + const pivotGrid = createPivotGrid({ dataSource: dataSource1 }); + this.clock.tick(10); + + assert.strictEqual(pivotGrid.getDataSource(), dataSource1, 'initial dataSource is dataSource1'); + assert.strictEqual(pivotGrid.$element().dxPivotGridFieldChooserBase('instance').option('dataSource'), dataSource1, 'FieldChooserBase uses dataSource1'); + + const initialOptionChangedListLength = pivotGrid._eventsStrategy._events.optionChanged._list.length; + + pivotGrid.option('dataSource', dataSource2); + this.clock.tick(10); + + assert.strictEqual(pivotGrid.getDataSource(), dataSource2, 'current dataSource is dataSource2 after first reassignment'); + assert.strictEqual(pivotGrid.$element().dxPivotGridFieldChooserBase('instance').option('dataSource'), dataSource2, 'FieldChooserBase uses dataSource2'); + assert.strictEqual(pivotGrid._eventsStrategy._events.optionChanged._list.length, initialOptionChangedListLength, 'optionChanged listener count does not grow after first reassignment'); + + pivotGrid.option('dataSource', dataSource3); + this.clock.tick(10); + + assert.strictEqual(pivotGrid.getDataSource(), dataSource3, 'current dataSource is dataSource3 after second reassignment'); + assert.strictEqual(pivotGrid.$element().dxPivotGridFieldChooserBase('instance').option('dataSource'), dataSource3, 'FieldChooserBase uses current dataSource (no stale reference to dataSource1 or dataSource2)'); + assert.strictEqual(pivotGrid._eventsStrategy._events.optionChanged._list.length, initialOptionChangedListLength, 'optionChanged listener count does not grow after multiple reassignments'); + }); + QUnit.test('not show field chooser popup on description area click when fieldChooser disabled', function(assert) { createPivotGrid({ fieldChooser: { From fac81f98ce13feafdf7df9c6b097ee8bb79f91bb Mon Sep 17 00:00:00 2001 From: AlisherAmonulloev Date: Sat, 31 Jan 2026 14:03:29 +0200 Subject: [PATCH 2/2] Update m_widget.ts --- packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts | 2 +- 1 file changed, 1 insertion(+), 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 c720b0366d37..e222956f6dc2 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/m_widget.ts @@ -1175,7 +1175,7 @@ class PivotGrid extends Widget { that.$element().addClass(OVERFLOW_HIDDEN_CLASS); const fieldChooserOptions = { - dataSource: that.option('dataSource'), + dataSource: that.getDataSource(), encodeHtml: that.option('encodeHtml'), allowFieldDragging: that.option('fieldPanel.allowFieldDragging'), headerFilter: that.option('headerFilter'),