From aaa687d7a71178e4e3e783b66d821c1c5cc05eed Mon Sep 17 00:00:00 2001 From: "anna.shakhova" <68295572+anna-shakhova@users.noreply.github.com> Date: Wed, 12 Aug 2026 14:41:14 +0200 Subject: [PATCH 1/4] Grids: move _stateStoringController definition from base dataController --- .../module_not_extended/state_storing.ts | 2 +- .../data_controller/data_controller.ts | 4 - .../state_storing_data_controller.ts | 86 +++++++++++++++++ .../state_storing/m_state_storing.ts | 93 +------------------ .../state_storing/state_storing_module.ts | 39 ++++++++ .../grids/tree_list/m_state_storing.ts | 2 +- 6 files changed, 132 insertions(+), 94 deletions(-) create mode 100644 packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts create mode 100644 packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts diff --git a/packages/devextreme/js/__internal/grids/data_grid/module_not_extended/state_storing.ts b/packages/devextreme/js/__internal/grids/data_grid/module_not_extended/state_storing.ts index 08b4bf5ad167..efd015421dce 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/module_not_extended/state_storing.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/module_not_extended/state_storing.ts @@ -1,4 +1,4 @@ -import { stateStoringModule } from '@ts/grids/grid_core/state_storing/m_state_storing'; +import { stateStoringModule } from '@ts/grids/grid_core/state_storing/state_storing_module'; import gridCore from '../m_core'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts index 3d1735dbfdba..b0e427215b2e 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts @@ -41,7 +41,6 @@ import type { } from '@ts/grids/grid_core/m_types'; import gridCoreUtils from '@ts/grids/grid_core/m_utils'; import type { SelectionController } from '@ts/grids/grid_core/selection/m_selection'; -import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; import type { VirtualScrollController } from '@ts/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core'; import { DataHelperMixin } from './data_helper_mixin'; @@ -151,8 +150,6 @@ export class DataController extends DataHelperMixin(modules.Controller) { protected _selectionController!: SelectionController; - protected _stateStoringController!: StateStoringController; - private loadErrorHandlerProxy!: (e: Error | string) => void; private dataPushedHandlerProxy!: (changes: StoreChange[]) => void; @@ -173,7 +170,6 @@ export class DataController extends DataHelperMixin(modules.Controller) { this._focusController = this.getController('focus'); this._headerFilterController = this.getController('headerFilter'); this._selectionController = this.getController('selection'); - this._stateStoringController = this.getController('stateStoring'); this._isPaging = false; this._currentOperationTypes = null; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts new file mode 100644 index 000000000000..ada92599e21d --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts @@ -0,0 +1,86 @@ +import type { Callback } from '@js/core/utils/callbacks'; +import { Deferred } from '@js/core/utils/deferred'; +import { isDefined } from '@js/core/utils/type'; +import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; +import type { ModuleType } from '@ts/grids/grid_core/m_types'; +import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; + +export interface StateStoringDataControllerExtension { + stateLoaded?: Callback<[]>; +} + +export const data = ( + Base: ModuleType, +): ModuleType< + DataController & StateStoringDataControllerExtension +> => class StateStoringDataExtender extends Base { + public stateLoaded?: Callback<[]>; + + protected _stateStoringController!: StateStoringController; + + private _restoreStateTimeoutID?: ReturnType | null; + + public init(): void { + this._stateStoringController = this.getController('stateStoring'); + super.init(); + } + + public dispose(): void { + clearTimeout(this._restoreStateTimeoutID ?? undefined); + super.dispose(); + } + + protected callbackNames(): string[] { + return super.callbackNames().concat(['stateLoaded']); + } + + // eslint-disable-next-line @stylistic/max-len + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type,@typescript-eslint/no-misused-promises + protected _refreshDataSource() { + if (this._stateStoringController.isEnabled() && !this._stateStoringController.isLoaded()) { + clearTimeout(this._restoreStateTimeoutID ?? undefined); + + const deferred = Deferred(); + // eslint-disable-next-line no-restricted-globals + this._restoreStateTimeoutID = setTimeout(() => { + this._stateStoringController.load() + .always(() => { + this._restoreStateTimeoutID = null; + }) + .done(() => { + super._refreshDataSource(); + + this.stateLoaded?.fire(); + deferred.resolve(); + }) + .fail((error) => { + this.stateLoaded?.fire(); + this._handleLoadError(error ?? 'Unknown error'); + deferred.reject(); + }); + }); + + return deferred.promise(); + } + + if (!this.isStateLoading()) { + super._refreshDataSource(); + } + + return undefined; + } + + public isLoading(): boolean { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return super.isLoading() || this._stateStoringController.isLoading(); + } + + private isStateLoading(): boolean { + return isDefined(this._restoreStateTimeoutID); + } + + public isLoaded(): boolean { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return super.isLoaded() && !this.isStateLoading(); + } +}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts index 54561fb88826..5e314ecd3f25 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts @@ -1,15 +1,13 @@ /* eslint-disable max-classes-per-file */ import { equalByValue, getKeyHash } from '@js/core/utils/common'; -import { Deferred } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; import { isDefined } from '@js/core/utils/type'; import type { ColumnsController } from '../columns_controller/m_columns_controller'; -import type { DataController } from '../data_controller/data_controller'; import type { ModuleType } from '../m_types'; import type { SelectionController } from '../selection/m_selection'; import type { RowsView } from '../views/m_rows_view'; -import { StateStoringController } from './m_state_storing_core'; +import type { StateStoringController } from './m_state_storing_core'; const getDataState = (that) => { // TODO getView @@ -91,7 +89,7 @@ const getFilterValue = (that, state) => { return that._initialFilterValue ?? filterSyncController.getFilterValueFromColumns(columns); }; -const rowsView = (Base: ModuleType) => class StateStoringRowsViewExtender extends Base { +export const rowsView = (Base: ModuleType) => class StateStoringRowsViewExtender extends Base { public init() { super.init(); @@ -109,7 +107,7 @@ const rowsView = (Base: ModuleType) => class StateStoringRowsViewExten } }; -const stateStoring = (Base: ModuleType) => class StateStoringExtender extends Base { +export const stateStoring = (Base: ModuleType) => class StateStoringExtender extends Base { private readonly _initialPageSize: any; public init() { @@ -209,7 +207,7 @@ const stateStoring = (Base: ModuleType) => class StateSt } }; -const columns = (Base: ModuleType) => class StateStoringColumnsExtender extends Base { +export const columns = (Base: ModuleType) => class StateStoringColumnsExtender extends Base { protected _shouldReturnVisibleColumns() { // @ts-expect-error const result = super._shouldReturnVisibleColumns.apply(this, arguments); @@ -218,59 +216,7 @@ const columns = (Base: ModuleType) => class StateStoringColum } }; -const data = (Base: ModuleType) => class StateStoringDataExtender extends Base { - private _restoreStateTimeoutID: any; - - public dispose() { - clearTimeout(this._restoreStateTimeoutID); - super.dispose(); - } - - protected callbackNames() { - return super.callbackNames().concat(['stateLoaded']); - } - - protected _refreshDataSource() { - if (this._stateStoringController.isEnabled() && !this._stateStoringController.isLoaded()) { - clearTimeout(this._restoreStateTimeoutID); - - // @ts-expect-error - const deferred = new Deferred(); - this._restoreStateTimeoutID = setTimeout(() => { - this._stateStoringController.load().always(() => { - this._restoreStateTimeoutID = null; - }).done(() => { - super._refreshDataSource(); - // @ts-expect-error - this.stateLoaded.fire(); - deferred.resolve(); - }).fail((error) => { - // @ts-expect-error - this.stateLoaded.fire(); - this.loadErrorHandler(error || 'Unknown error'); - deferred.reject(); - }); - }); - return deferred.promise(); - } if (!this.isStateLoading()) { - super._refreshDataSource(); - } - } - - public isLoading() { - return super.isLoading() || this._stateStoringController.isLoading(); - } - - private isStateLoading() { - return isDefined(this._restoreStateTimeoutID); - } - - public isLoaded() { - return super.isLoaded() && !this.isStateLoading(); - } -}; - -const selection = (Base: ModuleType) => class StateStoringSelectionExtender extends Base { +export const selection = (Base: ModuleType) => class StateStoringSelectionExtender extends Base { // eslint-disable-next-line @typescript-eslint/no-unused-vars protected _fireSelectionChanged(options) { const isDeferredSelection = this.option('selection.deferred'); @@ -281,32 +227,3 @@ const selection = (Base: ModuleType) => class StateStoringS super._fireSelectionChanged.apply(this, arguments); } }; - -export const stateStoringModule = { - defaultOptions() { - return { - stateStoring: { - enabled: false, - storageKey: undefined, - type: 'localStorage', - customLoad: undefined, - customSave: undefined, - savingTimeout: 2000, - }, - }; - }, - controllers: { - stateStoring: StateStoringController, - }, - extenders: { - views: { - rowsView, - }, - controllers: { - stateStoring, - columns, - data, - selection, - }, - }, -}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts new file mode 100644 index 000000000000..e65bdfdb0983 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts @@ -0,0 +1,39 @@ +import type { StateStoring } from '@js/common/grids'; + +import { data } from './extenders/state_storing_data_controller'; +import { + columns, + rowsView, + selection, + stateStoring, +} from './m_state_storing'; +import { StateStoringController } from './m_state_storing_core'; + +export const stateStoringModule = { + defaultOptions(): { stateStoring: StateStoring } { + return { + stateStoring: { + enabled: false, + storageKey: undefined, + type: 'localStorage', + customLoad: undefined, + customSave: undefined, + savingTimeout: 2000, + }, + }; + }, + controllers: { + stateStoring: StateStoringController, + }, + extenders: { + views: { + rowsView, + }, + controllers: { + stateStoring, + columns, + data, + selection, + }, + }, +}; diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts b/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts index 64f5545c6db1..645859ea163a 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts @@ -1,5 +1,5 @@ // eslint-disable-next-line max-classes-per-file -import { stateStoringModule } from '@ts/grids/grid_core/state_storing/m_state_storing'; +import { stateStoringModule } from '@ts/grids/grid_core/state_storing/state_storing_module'; import type { DataController } from '../grid_core/data_controller/data_controller'; import type { ModuleType } from '../grid_core/m_types'; From 59fc588f46fefd75739f1c013e5941895d98e50d Mon Sep 17 00:00:00 2001 From: "anna.shakhova" <68295572+anna-shakhova@users.noreply.github.com> Date: Thu, 13 Aug 2026 10:00:20 +0200 Subject: [PATCH 2/4] Grids: rename m_state_storing_core --- .../columns_controller/m_columns_controller.ts | 2 +- .../js/__internal/grids/grid_core/m_types.ts | 2 +- .../grids/grid_core/selection/m_selection.ts | 2 +- .../extenders/state_storing_data_controller.ts | 11 ++++++----- .../grids/grid_core/state_storing/m_state_storing.ts | 7 +++++-- ..._storing_core.ts => m_state_storing_controller.ts} | 0 .../grid_core/state_storing/state_storing_module.ts | 2 +- .../virtual_scrolling/m_virtual_scrolling.ts | 11 ++++++----- .../pivot_grid/data_controller/m_data_controller.ts | 2 +- .../js/__internal/grids/tree_list/m_state_storing.ts | 2 +- .../dataController.tests.js | 2 +- 11 files changed, 24 insertions(+), 19 deletions(-) rename packages/devextreme/js/__internal/grids/grid_core/state_storing/{m_state_storing_core.ts => m_state_storing_controller.ts} (100%) diff --git a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts index 3fb7d5270680..9ce02b89a247 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts @@ -23,7 +23,7 @@ import inflector from '@ts/core/utils/m_inflector'; import type { Column, ColumnsChanges, FilterField } from '@ts/grids/grid_core/columns_controller/types'; import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; import type { FocusController } from '@ts/grids/grid_core/focus/m_focus'; -import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; +import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_controller'; import { AI_COLUMN_NAME } from '../ai_column/const'; import modules from '../m_modules'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts index 10b13d15d308..2f94bd160ce7 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts @@ -207,7 +207,7 @@ export interface Controllers { selection: import('./selection/m_selection').SelectionController; validating: import('./validating/m_validating').ValidatingController; searchPanel: import('./search/m_search').SearchPanelViewController; - stateStoring: import('./state_storing/m_state_storing_core').StateStoringController; + stateStoring: import('./state_storing/m_state_storing_controller').StateStoringController; synchronizeScrolling: import('./views/m_grid_view').SynchronizeScrollingController; tablePosition: import('./columns_resizing_reordering/m_columns_resizing_reordering').TablePositionViewController; toastViewController: import('./toast/m_toast_controller').ToastViewController; diff --git a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts index 4c3316208268..85841f7d286f 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts @@ -20,7 +20,7 @@ import type { ColumnsController } from '@ts/grids/grid_core/columns_controller/m import type { Column } from '@ts/grids/grid_core/columns_controller/types'; import type { ContextMenuController } from '@ts/grids/grid_core/context_menu/m_context_menu'; import type { ModuleType } from '@ts/grids/grid_core/m_types'; -import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; +import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_controller'; import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view'; import Selection from '@ts/ui/selection/selection'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts index ada92599e21d..869afc61878d 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts @@ -3,10 +3,11 @@ import { Deferred } from '@js/core/utils/deferred'; import { isDefined } from '@js/core/utils/type'; import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; import type { ModuleType } from '@ts/grids/grid_core/m_types'; -import type { StateStoringController } from '@ts/grids/grid_core/state_storing/m_state_storing_core'; + +import type { StateStoringController } from '../m_state_storing_controller'; export interface StateStoringDataControllerExtension { - stateLoaded?: Callback<[]>; + stateLoaded: Callback<[]>; } export const data = ( @@ -14,7 +15,7 @@ export const data = ( ): ModuleType< DataController & StateStoringDataControllerExtension > => class StateStoringDataExtender extends Base { - public stateLoaded?: Callback<[]>; + public stateLoaded!: Callback<[]>; protected _stateStoringController!: StateStoringController; @@ -50,11 +51,11 @@ export const data = ( .done(() => { super._refreshDataSource(); - this.stateLoaded?.fire(); + this.stateLoaded.fire(); deferred.resolve(); }) .fail((error) => { - this.stateLoaded?.fire(); + this.stateLoaded.fire(); this._handleLoadError(error ?? 'Unknown error'); deferred.reject(); }); diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts index 5e314ecd3f25..c722f7a0cb2a 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts @@ -4,10 +4,12 @@ import { extend } from '@js/core/utils/extend'; import { isDefined } from '@js/core/utils/type'; import type { ColumnsController } from '../columns_controller/m_columns_controller'; +import type { DataController } from '../data_controller/data_controller'; import type { ModuleType } from '../m_types'; import type { SelectionController } from '../selection/m_selection'; import type { RowsView } from '../views/m_rows_view'; -import type { StateStoringController } from './m_state_storing_core'; +import type { StateStoringDataControllerExtension } from './extenders/state_storing_data_controller'; +import type { StateStoringController } from './m_state_storing_controller'; const getDataState = (that) => { // TODO getView @@ -90,10 +92,11 @@ const getFilterValue = (that, state) => { }; export const rowsView = (Base: ModuleType) => class StateStoringRowsViewExtender extends Base { + protected _dataController!: DataController & StateStoringDataControllerExtension; + public init() { super.init(); - // @ts-expect-error this._dataController.stateLoaded.add(() => { if (this._dataController.isLoaded() && !this._dataController.getDataSource()) { this.setLoading(false); diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts similarity index 100% rename from packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_core.ts rename to packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts index e65bdfdb0983..92563e291223 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts @@ -7,7 +7,7 @@ import { selection, stateStoring, } from './m_state_storing'; -import { StateStoringController } from './m_state_storing_core'; +import { StateStoringController } from './m_state_storing_controller'; export const stateStoringModule = { defaultOptions(): { stateStoring: StateStoring } { diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index e505c8d49f74..d5377e5de0c9 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -23,6 +23,7 @@ import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view'; import type { ChangedEvent } from '../data_source_adapter/types'; import gridCoreUtils from '../m_utils'; +import type { StateStoringDataControllerExtension } from '../state_storing/extenders/state_storing_data_controller'; import type { RowsViewScrollEvent } from '../views/types'; import { subscribeToExternalScrollers, VirtualScrollController } from './m_virtual_scrolling_core'; import type { ChangedLoadParams } from './types'; @@ -1434,6 +1435,8 @@ export const resizing = (Base: ModuleType) => class VirtualS }; export const rowsView = (Base: ModuleType) => class VirtualScrollingRowsViewExtender extends Base { + protected _dataController!: DataController & Partial; + private _isFixedTableRendering: any; private _heightWarningIsThrown: any; @@ -1461,11 +1464,9 @@ export const rowsView = (Base: ModuleType) => class VirtualScrollingRo !this._scrollTop && this._scrollToCurrentPageOnResize(); }); - this._dataController - // @ts-expect-error - .stateLoaded?.add(() => { - this._scrollToCurrentPageOnResize(); - }); + this._dataController.stateLoaded?.add(() => { + this._scrollToCurrentPageOnResize(); + }); this._scrollToCurrentPageOnResize(); } diff --git a/packages/devextreme/js/__internal/grids/pivot_grid/data_controller/m_data_controller.ts b/packages/devextreme/js/__internal/grids/pivot_grid/data_controller/m_data_controller.ts index 6171c3fd7f3c..9d7e4cd84b66 100644 --- a/packages/devextreme/js/__internal/grids/pivot_grid/data_controller/m_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/pivot_grid/data_controller/m_data_controller.ts @@ -5,7 +5,7 @@ import { extend } from '@js/core/utils/extend'; import { each, map } from '@js/core/utils/iterator'; import { format } from '@js/core/utils/string'; import { isDefined, isString } from '@js/core/utils/type'; -import stateStoring from '@ts/grids/grid_core/state_storing/m_state_storing_core'; +import stateStoring from '@ts/grids/grid_core/state_storing/m_state_storing_controller'; import { createColumnsInfo, foreachColumnInfo } from '@ts/grids/grid_core/virtual_columns/m_virtual_columns_core'; import VirtualScrollControllerModule from '@ts/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core'; diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts b/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts index 645859ea163a..b22989845d4e 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts @@ -3,7 +3,7 @@ import { stateStoringModule } from '@ts/grids/grid_core/state_storing/state_stor import type { DataController } from '../grid_core/data_controller/data_controller'; import type { ModuleType } from '../grid_core/m_types'; -import type { StateStoringController } from '../grid_core/state_storing/m_state_storing_core'; +import type { StateStoringController } from '../grid_core/state_storing/m_state_storing_controller'; import treeListCore from './m_core'; const stateStoring = ( diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataController.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataController.tests.js index 162bc0be14f3..07ada5ea3355 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataController.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataController.tests.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import Class from 'core/class'; import { DataController } from '__internal/grids/pivot_grid/data_controller/m_data_controller'; import virtualScrolling from '__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core'; -import stateStoring from '__internal/grids/grid_core/state_storing/m_state_storing_core'; +import stateStoring from '__internal/grids/grid_core/state_storing/m_state_storing_controller'; import pivotGridUtils from '__internal/grids/pivot_grid/m_widget_utils'; import { PivotGridDataSource } from '__internal/grids/pivot_grid/data_source/m_data_source'; From 9019b60a9a80d333ccec1dbb5de8217fbe15723e Mon Sep 17 00:00:00 2001 From: "anna.shakhova" <68295572+anna-shakhova@users.noreply.github.com> Date: Thu, 13 Aug 2026 10:26:52 +0200 Subject: [PATCH 3/4] Grids: fix typings --- .../grid_core/data_controller/data_controller.ts | 2 +- .../grid_core/data_controller/data_helper_mixin.ts | 5 ++++- .../extenders/state_storing_data_controller.ts | 11 +++++------ .../state_storing/m_state_storing_controller.ts | 4 ++-- .../grid_core/state_storing/state_storing_module.ts | 4 ++-- .../virtual_scrolling/m_virtual_scrolling.ts | 5 ++--- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts index b0e427215b2e..e54d3d3c75df 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts @@ -1301,7 +1301,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { /** * @extended: state_storing */ - public isLoading() { + public isLoading(): boolean { return this._isLoading || this._isCustomLoading; } diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts index c8fc65d55cb1..d80daa533091 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts @@ -1,5 +1,6 @@ import { DataSource } from '@js/common/data/data_source/data_source'; import { normalizeDataSourceOptions } from '@js/common/data/data_source/utils'; +import type { DeferredObj } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; import DataController from '@ts/ui/collection/m_data_controller'; @@ -49,9 +50,11 @@ export const DataHelperMixin = >(Base: T) => cl /** * @extended: state_storing, virtual_scrolling */ - protected _refreshDataSource(): void { + protected _refreshDataSource(): DeferredObj | undefined { this._initDataSource(); this._loadDataSource(); + + return undefined; } protected _initDataSource(): void { diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts index 869afc61878d..c7ff978f866c 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts @@ -1,4 +1,5 @@ import type { Callback } from '@js/core/utils/callbacks'; +import type { DeferredObj } from '@js/core/utils/deferred'; import { Deferred } from '@js/core/utils/deferred'; import { isDefined } from '@js/core/utils/type'; import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; @@ -10,11 +11,12 @@ export interface StateStoringDataControllerExtension { stateLoaded: Callback<[]>; } -export const data = ( +export const stateStoringDataControllerExtender = ( Base: ModuleType, ): ModuleType< DataController & StateStoringDataControllerExtension > => class StateStoringDataExtender extends Base { + // Defined in StateStoringRowsViewExtender.init() public stateLoaded!: Callback<[]>; protected _stateStoringController!: StateStoringController; @@ -35,9 +37,7 @@ export const data = ( return super.callbackNames().concat(['stateLoaded']); } - // eslint-disable-next-line @stylistic/max-len - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type,@typescript-eslint/no-misused-promises - protected _refreshDataSource() { + protected _refreshDataSource(): DeferredObj | undefined { if (this._stateStoringController.isEnabled() && !this._stateStoringController.isLoaded()) { clearTimeout(this._restoreStateTimeoutID ?? undefined); @@ -61,6 +61,7 @@ export const data = ( }); }); + // @ts-expect-error promise() is typed as Promise but returns a Deferred-like value at runtime return deferred.promise(); } @@ -72,7 +73,6 @@ export const data = ( } public isLoading(): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return super.isLoading() || this._stateStoringController.isLoading(); } @@ -81,7 +81,6 @@ export const data = ( } public isLoaded(): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return super.isLoaded() && !this.isStateLoading(); } }; diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts index 2ac42580aa0d..a7b9d0dc6b80 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts @@ -48,7 +48,7 @@ export class StateStoringController extends modules.ViewController { private _isLoaded: any; - private _isLoading: any; + private _isLoading!: boolean; private _windowUnloadHandler: any; @@ -145,7 +145,7 @@ export class StateStoringController extends modules.ViewController { return this._isLoaded; } - public isLoading() { + public isLoading(): boolean { return this._isLoading; } diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts index 92563e291223..d03b47138c2b 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts @@ -1,6 +1,6 @@ import type { StateStoring } from '@js/common/grids'; -import { data } from './extenders/state_storing_data_controller'; +import { stateStoringDataControllerExtender } from './extenders/state_storing_data_controller'; import { columns, rowsView, @@ -32,7 +32,7 @@ export const stateStoringModule = { controllers: { stateStoring, columns, - data, + data: stateStoringDataControllerExtender, selection, }, }, diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index d5377e5de0c9..4c61264302d7 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -477,9 +477,8 @@ export const data = (Base: ModuleType) => class VirtualScrolling super.dispose.apply(this, arguments as any); } - protected _refreshDataSource() { - // @ts-expect-error - const baseResult = super._refreshDataSource.apply(this, arguments as any) || new Deferred().resolve().promise(); + protected _refreshDataSource(): DeferredObj { + const baseResult = super._refreshDataSource() ?? Deferred().resolve(); baseResult.done(this.initVirtualRows.bind(this)); From 6a8b51a7ce2e70908f2914b07b1cd55b361a2ade Mon Sep 17 00:00:00 2001 From: "anna.shakhova" <68295572+anna-shakhova@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:21:19 +0200 Subject: [PATCH 4/4] fix review comments --- .../extenders/state_storing_data_controller.ts | 5 ++--- .../virtual_scrolling/m_virtual_scrolling.ts | 3 ++- .../js/__internal/grids/tree_list/m_widget.ts | 2 +- .../{m_state_storing.ts => state_storing.ts} | 16 ++++++++++++---- 4 files changed, 17 insertions(+), 9 deletions(-) rename packages/devextreme/js/__internal/grids/tree_list/{m_state_storing.ts => state_storing.ts} (63%) diff --git a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts index c7ff978f866c..1439fe03acce 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts @@ -16,7 +16,6 @@ export const stateStoringDataControllerExtender = ( ): ModuleType< DataController & StateStoringDataControllerExtension > => class StateStoringDataExtender extends Base { - // Defined in StateStoringRowsViewExtender.init() public stateLoaded!: Callback<[]>; protected _stateStoringController!: StateStoringController; @@ -54,9 +53,9 @@ export const stateStoringDataControllerExtender = ( this.stateLoaded.fire(); deferred.resolve(); }) - .fail((error) => { + .fail((error: Error) => { this.stateLoaded.fire(); - this._handleLoadError(error ?? 'Unknown error'); + this.loadErrorHandler(error ?? 'Unknown error'); deferred.reject(); }); }); diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index 4c61264302d7..9f06035646d1 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -478,7 +478,8 @@ export const data = (Base: ModuleType) => class VirtualScrolling } protected _refreshDataSource(): DeferredObj { - const baseResult = super._refreshDataSource() ?? Deferred().resolve(); + // @ts-expect-error promise() is typed as Promise but returns a Deferred-like value at runtime + const baseResult: DeferredObj = super._refreshDataSource() ?? Deferred().resolve().promise(); baseResult.done(this.initVirtualRows.bind(this)); diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_widget.ts b/packages/devextreme/js/__internal/grids/tree_list/m_widget.ts index 2a89ba216c6f..ec4c9eb74697 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_widget.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_widget.ts @@ -2,7 +2,7 @@ /* eslint-disable simple-import-sort/imports */ import TreeList from './m_widget_base'; -import './m_state_storing'; +import './state_storing'; import './module_not_extended/ai_column'; import './module_not_extended/column_chooser'; import './m_master_detail'; diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts b/packages/devextreme/js/__internal/grids/tree_list/state_storing.ts similarity index 63% rename from packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts rename to packages/devextreme/js/__internal/grids/tree_list/state_storing.ts index b22989845d4e..4b237e20db1d 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/state_storing.ts @@ -1,4 +1,8 @@ // eslint-disable-next-line max-classes-per-file +import type { UserState } from '@ts/grids/grid_core/data_controller/types'; +import type { + StateStoringDataControllerExtension, +} from '@ts/grids/grid_core/state_storing/extenders/state_storing_data_controller'; import { stateStoringModule } from '@ts/grids/grid_core/state_storing/state_storing_module'; import type { DataController } from '../grid_core/data_controller/data_controller'; @@ -8,8 +12,9 @@ import treeListCore from './m_core'; const stateStoring = ( Base: ModuleType, -) => class TreeListStateStoringExtender extends stateStoringModule.extenders.controllers.stateStoring(Base) { - protected applyState(state) { + // eslint-disable-next-line @stylistic/max-len +): ModuleType => class TreeListStateStoringExtender extends stateStoringModule.extenders.controllers.stateStoring(Base) { + protected applyState(state): void { super.applyState(state); this.option('expandedRowKeys', state.expandedRowKeys ? state.expandedRowKeys.slice() : []); } @@ -17,8 +22,11 @@ const stateStoring = ( const data = ( Base: ModuleType, -) => class TreeListStateStoringDataExtender extends stateStoringModule.extenders.controllers.data(Base) { - public getUserState() { +): ModuleType< + DataController & StateStoringDataControllerExtension +// eslint-disable-next-line @stylistic/max-len +> => class TreeListStateStoringDataExtender extends stateStoringModule.extenders.controllers.data(Base) { + public getUserState(): UserState { const state = super.getUserState(); if (!this.option('autoExpandAll')) {