Skip to content

Grids: move _stateStoringController definition from base dataController - #34752

Open
anna-shakhova wants to merge 4 commits into
DevExpress:mainfrom
anna-shakhova:move_state_storing_main
Open

Grids: move _stateStoringController definition from base dataController#34752
anna-shakhova wants to merge 4 commits into
DevExpress:mainfrom
anna-shakhova:move_state_storing_main

Conversation

@anna-shakhova

Copy link
Copy Markdown
Contributor

No description provided.

@anna-shakhova anna-shakhova self-assigned this Aug 12, 2026
@anna-shakhova
anna-shakhova force-pushed the move_state_storing_main branch from bb213c8 to bb36f4a Compare August 13, 2026 08:27
@anna-shakhova
anna-shakhova marked this pull request as ready for review August 13, 2026 08:28
@anna-shakhova
anna-shakhova requested review from a team as code owners August 13, 2026 08:28
Copilot AI lite review requested due to automatic review settings August 13, 2026 08:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Grid state storing implementation by extracting the _stateStoringController-related DataController logic into a dedicated state-storing DataController extender, and reorganizes the state-storing module definition into a standalone module file. This aligns the state-storing responsibilities with the module/extender architecture rather than keeping them in the base DataController.

Changes:

  • Split the state-storing “data controller” extender into state_storing/extenders/state_storing_data_controller.ts and updated state-storing module wiring accordingly.
  • Introduced state_storing_module.ts as the canonical stateStoringModule export and updated TreeList/DataGrid module registrations to consume it.
  • Updated various imports/types and tightened several method/property typings (notably around _refreshDataSource() and loading flags).

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/devextreme/testing/tests/DevExpress.ui.widgets.pivotGrid/dataController.tests.js Updated PivotGrid test to import the StateStoringController from its new location.
packages/devextreme/js/__internal/grids/tree_list/m_state_storing.ts Switched to the new stateStoringModule export and updated controller type import.
packages/devextreme/js/__internal/grids/pivot_grid/data_controller/m_data_controller.ts Updated StateStoringController import path for PivotGrid’s internal controller usage.
packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts Adjusted _refreshDataSource() typing/behavior and typed stateLoaded usage via a new extender interface.
packages/devextreme/js/__internal/grids/grid_core/state_storing/state_storing_module.ts Added new central stateStoringModule definition (controllers + extenders wiring).
packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing.ts Removed embedded module definition and extracted data-extender logic; exported extenders for module composition.
packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts Tightened typing for _isLoading and isLoading() return type.
packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts Added new DataController extender that owns state-storing load/refresh coordination and stateLoaded callback.
packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts Updated StateStoringController type import path.
packages/devextreme/js/__internal/grids/grid_core/m_types.ts Updated Controllers typing to reference the new StateStoringController import path.
packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts Updated _refreshDataSource() signature to return `DeferredObj
packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts Removed base _stateStoringController initialization and tightened isLoading() return type.
packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts Updated StateStoringController type import path.
packages/devextreme/js/__internal/grids/data_grid/module_not_extended/state_storing.ts Updated DataGrid module registration to use the new stateStoringModule export.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@anna-shakhova
anna-shakhova force-pushed the move_state_storing_main branch from bb36f4a to 171f478 Compare August 13, 2026 08:47
Copilot AI review requested due to automatic review settings August 13, 2026 08:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts:20

  • The comment says stateLoaded is defined in StateStoringRowsViewExtender.init(), but that method only subscribes to stateLoaded; the callback is actually created by the controller base based on callbackNames() (see callbackNames(): string[] in this extender). This comment is misleading and makes the lifecycle harder to understand.
  // Defined in StateStoringRowsViewExtender.init()
  public stateLoaded!: Callback<[]>;

@Alyar666
Alyar666 self-requested a review August 13, 2026 11:13
// @ts-expect-error
const baseResult = super._refreshDataSource.apply(this, arguments as any) || new Deferred().resolve().promise();
protected _refreshDataSource(): DeferredObj<unknown> {
const baseResult = super._refreshDataSource() ?? Deferred().resolve();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s an inconsistency in the return value here. In the other extender, we return a Promise, while here we return resolve. Should we return a Promise here as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we used .promise() as default value, returned it
But had to add expect-error here due to incorrect typings in Deferred

};

export const rowsView = (Base: ModuleType<RowsView>) => class VirtualScrollingRowsViewExtender extends Base {
protected _dataController!: DataController & Partial<StateStoringDataControllerExtension>;

@Alyar666 Alyar666 Aug 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is _dataController typed differently?

state_storing rowsView: DataController & StateStoringDataControllerExtension
virtual_scrolling rowsView: DataController & Partial<StateStoringDataControllerExtension>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StateStoringDataControllerExtension belongs to state_storing module. So in its RowsViewExtension corresponding callback will always present - we define them simultaneously.
VirtualScrolling is another independent module, and here we add type as Partial - in case stateStoring was not registered before virtualScrolling - we never face it, but it is more honest type


export const stateStoringDataControllerExtender = (
Base: ModuleType<DataController>,
): ModuleType<

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explicit return type erases the Base type. This is important for TreeList, which extends the result:
class TreeListStateStoringDataExtender extends stateStoringModule.extenders.controllers.data(Base)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no issue, TreeListStateStoringDataExtender will have same type as stateStoringModule.extenders.controllers.data - we call here extender function, with proper argument.
Removed m_prefix from TreeList module to make it transparent

Copilot AI review requested due to automatic review settings August 13, 2026 12:23
@anna-shakhova
anna-shakhova force-pushed the move_state_storing_main branch from 171f478 to f8a231d Compare August 13, 2026 12:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Copilot AI review requested due to automatic review settings August 13, 2026 12:46
@anna-shakhova
anna-shakhova force-pushed the move_state_storing_main branch from f8a231d to fc44410 Compare August 13, 2026 12:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/devextreme/js/__internal/grids/grid_core/state_storing/m_state_storing_controller.ts:51

  • _isLoading is marked with definite assignment (!) but isLoading() can be called before init() in some lifecycles, which would return undefined at runtime while being typed as boolean. Initializing it at declaration makes the runtime behavior match the type and removes reliance on init ordering.
    packages/devextreme/js/__internal/grids/grid_core/state_storing/extenders/state_storing_data_controller.ts:60
  • The Deferred fail callback from load() is not guaranteed to pass an Error instance; it may be a string/undefined depending on the underlying promise/Deferred. Using error ?? 'Unknown error' also changes the previous fallback semantics ('' would no longer map to the default), which can result in an empty/unclear error being passed to loadErrorHandler.
          .fail((error: Error) => {
            this.stateLoaded.fire();
            this.loadErrorHandler(error ?? 'Unknown error');
            deferred.reject();
          });

@Alyar666
Alyar666 self-requested a review August 13, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants