From 6306502063ac71bdf703524c01c3b8be4c6aca83 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Wed, 12 Aug 2026 17:02:12 +0400 Subject: [PATCH 1/2] GridCore dataController: fix ESLint errors in the updateItems block --- .../data_controller/data_controller.ts | 242 +++++++++--------- .../grids/grid_core/data_controller/types.ts | 6 + .../utils/__tests__/row_changes.test.ts | 103 +++++++- .../data_controller/utils/row_changes.ts | 77 +++++- .../grids/grid_core/editing/m_editing.ts | 4 +- .../m_keyboard_navigation.ts | 4 +- 6 files changed, 298 insertions(+), 138 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 3d1735dbfdba..c43b41cf6c03 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 @@ -3,13 +3,9 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-floating-promises */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -/* eslint-disable @typescript-eslint/no-shadow */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable consistent-return */ /* eslint-disable no-param-reassign */ -/* eslint-disable no-plusplus */ import type { Store } from '@js/common/data'; import type { Callback } from '@js/core/utils/callbacks'; import { deferRender } from '@js/core/utils/common'; @@ -48,10 +44,12 @@ import { DataHelperMixin } from './data_helper_mixin'; import type { BinaryDataFilterExpression, CallbackFlags, + ChangedRows, DataChange, DataFilter, DataSourceAdapterLike, GeneratedItem, + ItemChange, ItemProcessingOptions, PagingChanges, PagingDataSource, @@ -59,6 +57,7 @@ import type { PagingResult, ProcessedItem, RefreshOptions, + RowIndexByKey, UpdateChange, UpdateRowChange, UserState, @@ -66,7 +65,9 @@ import type { import { resolvePaginate, syncPaging } from './utils/paging'; import { getRefreshOptions } from './utils/refresh'; import { - getChangedRowIndices, getRowOperation, isSameGroupRowState, pushChangedRow, resetChangedRows, + convertToUpdateChange, createChangedRows, getChangedRowIndices, getDataRowIndex, + getRowKey, getRowOperation, indexRowsByKey, isSameGroupRowState, pushChangedRow, + resetChangedRows, updateRowCells, } from './utils/row_changes'; import { generateRowValues } from './utils/row_values'; @@ -805,7 +806,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { this.applyChangeUpdate(change); } else if (change.changeType === 'refresh') { if (this.items().length && change.repaintChangesOnly) { - this._applyChangesOnly(change); + this.applyChangesOnly(change); } else { this._applyChangeFull(change); } @@ -1042,123 +1043,120 @@ export class DataController extends DataHelperMixin(modules.Controller) { return true; } - /** - * @extended: editing - */ - protected _applyChangesOnly(change) { - const rowIndices: any[] = []; - const columnIndices: any[] = []; - const changeTypes: string[] = []; - const items: any[] = []; - const newIndexByKey = {}; - const isLiveUpdate = change?.isLiveUpdate ?? true; - - function getRowKey(row) { - if (row) { - return `${row.rowType},${JSON.stringify(row.key)}`; + private applyItemChange( + itemChange: ItemChange, + isLiveUpdate: boolean, + ): UpdateRowChange | undefined { + const { index } = itemChange; + + switch (itemChange.type) { + case 'update': { + const newItem = itemChange.data; + const columnIndices = this._partialUpdateRow( + itemChange.oldItem, + newItem, + index, + isLiveUpdate, + ); + + this._items[index] = newItem; + + return { + changeType: 'update', rowIndex: index, item: newItem, columnIndices, + }; } - - return undefined; + case 'insert': + this._items.splice(index, 0, itemChange.data); + return { changeType: 'insert', rowIndex: index, item: itemChange.data }; + case 'remove': + this._items.splice(index, 1); + return { changeType: 'remove', rowIndex: index, item: itemChange.oldItem }; + default: + return undefined; } + } - const isItemEquals = (item1, item2) => { + private findItemChanges( + oldItems: ProcessedItem[], + newItems: ProcessedItem[], + ): ItemChange[] | undefined { + const isItemEquals = (item1: ProcessedItem, item2: ProcessedItem): boolean => { if (!this._isItemEquals(item1, item2)) { return false; } - if (item1.cells) { - item1.update?.(item2); - item1.cells.forEach((cell) => { - if (cell?.update) { - cell.update(item2, true); - } - }); - } + updateRowCells(item1, item2); return true; }; - const currentItems = this._items; - const oldItems = currentItems.slice(); - - change.items.forEach((item, index) => { - const key = getRowKey(item); - newIndexByKey[key!] = index; - item.rowIndex = index; - }); - - const result = findChanges({ + return findChanges({ oldItems, - newItems: change.items, + newItems, getKey: getRowKey, isItemEquals, }); + } + + private applyItemChanges(itemChanges: ItemChange[], isLiveUpdate: boolean): ChangedRows { + const changedRows = createChangedRows(); + + itemChanges.forEach((itemChange) => { + const changedRow = this.applyItemChange(itemChange, isLiveUpdate); + + if (changedRow) { + pushChangedRow(changedRows, changedRow); + } + }); + + return changedRows; + } + + private getRowIndexCorrection( + rowIndex: number, + oldItems: ProcessedItem[], + newIndexByKey: RowIndexByKey, + ): number { + const oldRowIndexOffset = this._rowIndexOffset || 0; + const rowIndexOffset = this.getRowIndexOffset(); + const oldItem = oldItems[rowIndex - oldRowIndexOffset]; + const newVisibleRowIndex = oldItem ? newIndexByKey[getRowKey(oldItem)] : undefined; + + return newVisibleRowIndex === undefined ? 0 : newVisibleRowIndex + rowIndexOffset - rowIndex; + } - if (!result) { + /** + * @extended: editing + */ + protected applyChangesOnly(change: DataChange): void { + const newItems = change.items ?? []; + const oldItems = this._items.slice(); + const newIndexByKey = indexRowsByKey(newItems); + const itemChanges = this.findItemChanges(oldItems, newItems); + + if (!itemChanges) { this._applyChangeFull(change); return; } - result.forEach((change) => { - switch (change.type) { - case 'update': { - const { index } = change; - const newItem = change.data; - const { oldItem } = change; - const changedColumnIndices = this._partialUpdateRow(oldItem, newItem, index, isLiveUpdate); - - rowIndices.push(index); - changeTypes.push('update'); - items.push(newItem); - currentItems[index] = newItem; - columnIndices.push(changedColumnIndices); - break; - } - case 'insert': - rowIndices.push(change.index); - changeTypes.push('insert'); - items.push(change.data); - columnIndices.push(undefined); - currentItems.splice(change.index, 0, change.data); - break; - case 'remove': - rowIndices.push(change.index); - changeTypes.push('remove'); - currentItems.splice(change.index, 1); - items.push(change.oldItem); - columnIndices.push(undefined); - break; - default: - break; - } - }); + const changedRows = this.applyItemChanges(itemChanges, change.isLiveUpdate ?? true); + + convertToUpdateChange(change, changedRows); - change.repaintChangesOnly = true; - change.changeType = 'update'; - change.rowIndices = rowIndices; - change.columnIndices = columnIndices; - change.changeTypes = changeTypes; - change.items = items; if (oldItems.length) { change.isLiveUpdate = true; } - this._correctRowIndices((rowIndex) => { - const oldRowIndexOffset = this._rowIndexOffset || 0; - const rowIndexOffset = this.getRowIndexOffset(); - const oldItem = oldItems[rowIndex - oldRowIndexOffset]; - const key = getRowKey(oldItem); - const newVisibleRowIndex = newIndexByKey[key!]; - - return newVisibleRowIndex >= 0 ? newVisibleRowIndex + rowIndexOffset - rowIndex : 0; - }); + this.correctRowIndices( + (rowIndex) => this.getRowIndexCorrection(rowIndex, oldItems, newIndexByKey), + ); } /** * @extended: keyboard_navigation */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected _correctRowIndices(rowIndex: any): any { } + protected correctRowIndices(getRowIndexCorrection: (rowIndex: number) => number): void { } /** * @extend: virtual_scrolling @@ -1185,7 +1183,8 @@ export class DataController extends DataHelperMixin(modules.Controller) { return cachedProcessedItems; } - // change.items at this stage is defined only if virtualScrolling + legacyScrollingMode enabled + // change.items at this stage is defined only if virtualScrolling + // + legacyScrollingMode enabled const dataItems = this._beforeProcessItems(change.items ?? dataSource.items()); const processedItems = this._processItems(dataItems, change); @@ -1225,32 +1224,21 @@ export class DataController extends DataHelperMixin(modules.Controller) { const rows = this.getVisibleRows(); const dataSource = this.dataSource(); - if (dataSource) { - e.changes.forEach((change) => { - if (change.index === undefined) { - return; - } - - if (change.type === 'insert' && change.index >= 0) { - let dataIndex = 0; - - for (let i = 0; i < change.index; i++) { - const row = rows[i]; - if (row && (row.rowType === 'data' || row.rowType === 'group')) { - dataIndex++; - } - } - - change.index = dataIndex; - } - }); + if (!dataSource) { + return; } + + e.changes.forEach((change) => { + if (change.type === 'insert' && change.index !== undefined && change.index >= 0) { + change.index = getDataRowIndex(rows, change.index); + } + }); }; public updateItems( change: DataChange = { changeType: 'refresh' }, isDataChanged?: boolean, - ) { + ): void { change.isFirstRender = !this.changed.fired(); if (this._repaintChangesOnly !== undefined) { @@ -1259,10 +1247,11 @@ export class DataController extends DataHelperMixin(modules.Controller) { } else if (change.changes) { change.repaintChangesOnly = this.option('repaintChangesOnly'); } else if (isDataChanged) { - const operationTypes = this.dataSource().operationTypes(); + const operationTypes: OperationTypes | undefined = this.dataSource().operationTypes(); change.isDataChanged = true; - change.repaintChangesOnly = operationTypes && !operationTypes.grouping && !operationTypes.filtering && this.option('repaintChangesOnly'); + change.repaintChangesOnly = operationTypes && !operationTypes.grouping + && !operationTypes.filtering && this.option('repaintChangesOnly'); if (this.needUpdateDimensions(operationTypes)) { change.needUpdateDimensions = true; @@ -1281,23 +1270,28 @@ export class DataController extends DataHelperMixin(modules.Controller) { this._fireChanged(change); } - protected needUpdateDimensions(operationTypes: OperationTypes) { - return operationTypes && ( - operationTypes.reload || operationTypes.paging || operationTypes.groupExpanding + /** + * @extended: TreeList's data_controller + */ + protected needUpdateDimensions(operationTypes?: OperationTypes): boolean { + return Boolean( + operationTypes?.reload || operationTypes?.paging || operationTypes?.groupExpanding, ); } - public loadingOperationTypes() { + public loadingOperationTypes(): OperationTypes { const dataSource = this.dataSource(); + const operationTypes: OperationTypes | undefined = dataSource?.loadingOperationTypes(); - return dataSource?.loadingOperationTypes() || {}; + return operationTypes ?? {}; } /** * @extended: virtual_scrolling, focus */ - protected _fireChanged(change) { - deferRender(() => { + protected _fireChanged(change: DataChange): void { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + deferRender((): void => { this.changed.fire(change); }); } @@ -1305,11 +1299,11 @@ export class DataController extends DataHelperMixin(modules.Controller) { /** * @extended: state_storing */ - public isLoading() { + public isLoading(): boolean { return this._isLoading || this._isCustomLoading; } - private _fireLoadingChanged() { + private _fireLoadingChanged(): void { this.loadingChanged.fire(this.isLoading(), this._loadingText); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts index 0b6a7b193ced..0a93d4f8a026 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts @@ -132,6 +132,12 @@ export interface UpdateRowChange { columnIndices?: number[]; } +export type RowIndexByKey = Record; + +export type ItemChange = | { type: 'insert'; index: number; data: ProcessedItem } + | { type: 'update'; index: number; data: ProcessedItem; oldItem: ProcessedItem } + | { type: 'remove'; index: number; oldItem: ProcessedItem }; + /** data source */ export interface DataSourceAdapterLike { diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts index 86c51a61efdc..2aea114a2737 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts @@ -1,9 +1,14 @@ -import { describe, expect, it } from '@jest/globals'; +import { + describe, expect, it, jest, +} from '@jest/globals'; -import type { ChangedRows, ProcessedItem, UpdateChange } from '../../types'; +import type { + ChangedRows, DataChange, ProcessedItem, UpdateChange, +} from '../../types'; import { - getChangedRowIndices, getRowOperation, isSameGroupRowState, - isSameItem, pushChangedRow, resetChangedRows, + convertToUpdateChange, getChangedRowIndices, getDataRowIndex, getRowKey, + getRowOperation, indexRowsByKey, isSameGroupRowState, isSameItem, + pushChangedRow, resetChangedRows, updateRowCells, } from '../row_changes'; const row = (partial: Partial): ProcessedItem => ({ @@ -111,6 +116,77 @@ describe('isSameGroupRowState', () => { }); }); +describe('getRowKey', () => { + it('should tell apart the rows of different types with the same key', () => { + expect(getRowKey(row({ key: 1, rowType: 'data' }))) + .not.toBe(getRowKey(row({ key: 1, rowType: 'detail' }))); + }); + + it('should return the same key for equal composite keys', () => { + expect(getRowKey(row({ key: { id: 1, room: 2 } }))) + .toBe(getRowKey(row({ key: { id: 1, room: 2 } }))); + }); +}); + +describe('indexRowsByKey', () => { + it('should number the rows and map their keys to the indices', () => { + const items = [row({ key: 1 }), row({ key: 2 })]; + + const indexByKey = indexRowsByKey(items); + + expect(items.map((item) => item.rowIndex)).toEqual([0, 1]); + expect(indexByKey[getRowKey(items[0])]).toBe(0); + expect(indexByKey[getRowKey(items[1])]).toBe(1); + }); + + it('should return undefined for an unknown key', () => { + const indexByKey = indexRowsByKey([row({ key: 1 })]); + + expect(indexByKey[getRowKey(row({ key: 2 }))]).toBeUndefined(); + }); +}); + +describe('updateRowCells', () => { + it('should pass the new row to the row and cell updaters', () => { + const newItem = row({ key: 1 }); + const update = jest.fn(); + const cellUpdate = jest.fn(); + const oldItem = row({ key: 1, update, cells: [{ update: cellUpdate }, {}] }); + + updateRowCells(oldItem, newItem); + + expect(update).toHaveBeenCalledWith(newItem); + expect(cellUpdate).toHaveBeenCalledWith(newItem, true); + }); + + it('should do nothing when the row has no cells', () => { + const update = jest.fn(); + + updateRowCells(row({ key: 1, update }), row({ key: 1 })); + + expect(update).not.toHaveBeenCalled(); + }); +}); + +describe('getDataRowIndex', () => { + const rows = [ + row({ rowType: 'data' }), + row({ rowType: 'group' }), + row({ rowType: 'detail' }), + row({ rowType: 'data' }), + ]; + + it('should count the data and group rows before the visible index', () => { + expect(getDataRowIndex(rows, 0)).toBe(0); + expect(getDataRowIndex(rows, 3)).toBe(2); + expect(getDataRowIndex(rows, rows.length)).toBe(3); + }); + + it('should count the rows that are there when the index is out of range', () => { + expect(getDataRowIndex(rows, 10)).toBe(3); + }); +}); + describe('getChangedRowIndices', () => { it('should sort the indices ascending', () => { expect(getChangedRowIndices([4, 0, 2], 0)).toEqual([0, 2, 4]); @@ -206,6 +282,25 @@ describe('resetChangedRows', () => { }); }); +describe('convertToUpdateChange', () => { + const refreshChange = (): DataChange => ({ changeType: 'refresh', items: [row({ key: 1 })] }); + + it('should turn the refresh change into a partial update carrying the rows', () => { + const change = refreshChange(); + const changedRows = emptyChangedRows(); + + convertToUpdateChange(change, changedRows); + + const updateChange = change as UpdateChange; + expect(updateChange.changeType).toBe('update'); + expect(updateChange.repaintChangesOnly).toBe(true); + expect(updateChange.items).toBe(changedRows.items); + expect(updateChange.rowIndices).toBe(changedRows.rowIndices); + expect(updateChange.changeTypes).toBe(changedRows.changeTypes); + expect(updateChange.columnIndices).toBe(changedRows.columnIndices); + }); +}); + describe('pushChangedRow', () => { it('should push the changed row to every list', () => { const changedRows = emptyChangedRows(); diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts index 2de3a2fb2297..17d5780dee7c 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts @@ -1,8 +1,8 @@ import { equalByValue } from '@js/core/utils/common'; import type { - ChangedRows, ProcessedItem, RowOperation, UpdateChange, - UpdateRowChange, + ChangedRows, DataChange, ProcessedItem, RowIndexByKey, + RowOperation, UpdateChange, UpdateRowChange, } from '../types'; export function isSameItem( @@ -31,6 +31,54 @@ export function isSameGroupRowState(item1: ProcessedItem, item2: ProcessedItem): && item1.data?.isContinuationOnNextPage === item2.data?.isContinuationOnNextPage; } +/** + * Rows of different types may share a key, so the row type is a part of the key + * the diff is built on. + */ +export function getRowKey(row: ProcessedItem): string { + return `${row.rowType},${JSON.stringify(row.key)}`; +} + +/** + * Numbers the rows and maps their keys to the new indices: both the diff and + * the row index correction look rows up by key. + */ +export function indexRowsByKey(items: ProcessedItem[]): RowIndexByKey { + const indexByKey: RowIndexByKey = {}; + + items.forEach((item, index) => { + indexByKey[getRowKey(item)] = index; + item.rowIndex = index; + }); + + return indexByKey; +} + +/** + * A row that only got new data keeps its cells: the updaters the rows view has + * installed on the row and on every cell take the new row in place. + */ +export function updateRowCells(oldItem: ProcessedItem, newItem: ProcessedItem): void { + if (!oldItem.cells) { + return; + } + + oldItem.update?.(newItem); + oldItem.cells.forEach((cell) => { + cell?.update?.(newItem, true); + }); +} + +/** + * A store change is indexed by data rows, while an insert index coming from the + * grid counts every visible row — group rows included. + */ +export function getDataRowIndex(rows: ProcessedItem[], visibleRowIndex: number): number { + const previousRows = rows.slice(0, visibleRowIndex); + + return previousRows.filter((row) => row?.rowType === 'data' || row?.rowType === 'group').length; +} + export function getChangedRowIndices( rowIndices: number[], rowIndexDelta: number, @@ -76,22 +124,39 @@ export function getRowOperation( return newItem ? 'replace' : undefined; } -export function resetChangedRows(change: UpdateChange): ChangedRows { - const changedRows: ChangedRows = { +export function createChangedRows(): ChangedRows { + return { items: [], rowIndices: [], changeTypes: [], columnIndices: [], }; +} - change.items = changedRows.items; +function setChangedRows(change: UpdateChange, changedRows: ChangedRows): void { change.rowIndices = changedRows.rowIndices; - change.changeTypes = changedRows.changeTypes; change.columnIndices = changedRows.columnIndices; + change.changeTypes = changedRows.changeTypes; + change.items = changedRows.items; +} + +export function resetChangedRows(change: UpdateChange): ChangedRows { + const changedRows = createChangedRows(); + + setChangedRows(change, changedRows); return changedRows; } +export function convertToUpdateChange(change: DataChange, changedRows: ChangedRows): void { + const updateChange = change as UpdateChange; + + updateChange.repaintChangesOnly = true; + updateChange.changeType = 'update'; + + setChangedRows(updateChange, changedRows); +} + export function pushChangedRow(changedRows: ChangedRows, changedRow: UpdateRowChange): void { const { item, rowIndex, changeType, columnIndices, diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index 31bcc799801d..a272c1942da7 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts @@ -2580,9 +2580,9 @@ export const dataControllerEditingExtenderMixin = (Base: ModuleType) => class EditingController }; const data = (Base: ModuleType) => class DataControllerKeyboardExtender extends Base { - protected _correctRowIndices(getRowIndexCorrection) { + protected correctRowIndices(getRowIndexCorrection) { const that = this; const focusedCellPosition = this._keyboardNavigationController._focusedCellPosition; - super._correctRowIndices.apply(that, arguments as any); + super.correctRowIndices.apply(that, arguments as any); if (focusedCellPosition && focusedCellPosition.rowIndex >= 0) { const focusedRowIndexCorrection = getRowIndexCorrection(focusedCellPosition.rowIndex); From 1a09baab9e18707b72f506f5b7d7d36efe6ed8b0 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Thu, 13 Aug 2026 23:34:21 +0400 Subject: [PATCH 2/2] Fix comments --- .../data_controller/data_controller.ts | 18 +++++++++++++----- .../utils/__tests__/row_changes.test.ts | 8 ++++---- .../data_controller/utils/row_changes.ts | 12 ++++++------ .../m_keyboard_navigation.ts | 3 +-- 4 files changed, 24 insertions(+), 17 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 c43b41cf6c03..4b956655a1da 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 @@ -65,9 +65,17 @@ import type { import { resolvePaginate, syncPaging } from './utils/paging'; import { getRefreshOptions } from './utils/refresh'; import { - convertToUpdateChange, createChangedRows, getChangedRowIndices, getDataRowIndex, - getRowKey, getRowOperation, indexRowsByKey, isSameGroupRowState, pushChangedRow, - resetChangedRows, updateRowCells, + getChangedRowIndices, + getDataRowIndex, + getRowKey, + getRowOperation, + indexRowsByKey, + initChangedRows, + isSameGroupRowState, + markUpdateChange, + pushChangedRow, + resetChangedRows, + updateRowCells, } from './utils/row_changes'; import { generateRowValues } from './utils/row_values'; @@ -1099,7 +1107,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { } private applyItemChanges(itemChanges: ItemChange[], isLiveUpdate: boolean): ChangedRows { - const changedRows = createChangedRows(); + const changedRows = initChangedRows(); itemChanges.forEach((itemChange) => { const changedRow = this.applyItemChange(itemChange, isLiveUpdate); @@ -1141,7 +1149,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { const changedRows = this.applyItemChanges(itemChanges, change.isLiveUpdate ?? true); - convertToUpdateChange(change, changedRows); + markUpdateChange(change, changedRows); if (oldItems.length) { change.isLiveUpdate = true; diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts index 2aea114a2737..49ef583a7b01 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/__tests__/row_changes.test.ts @@ -6,9 +6,9 @@ import type { ChangedRows, DataChange, ProcessedItem, UpdateChange, } from '../../types'; import { - convertToUpdateChange, getChangedRowIndices, getDataRowIndex, getRowKey, + getChangedRowIndices, getDataRowIndex, getRowKey, getRowOperation, indexRowsByKey, isSameGroupRowState, isSameItem, - pushChangedRow, resetChangedRows, updateRowCells, + markUpdateChange, pushChangedRow, resetChangedRows, updateRowCells, } from '../row_changes'; const row = (partial: Partial): ProcessedItem => ({ @@ -282,14 +282,14 @@ describe('resetChangedRows', () => { }); }); -describe('convertToUpdateChange', () => { +describe('markUpdateChange', () => { const refreshChange = (): DataChange => ({ changeType: 'refresh', items: [row({ key: 1 })] }); it('should turn the refresh change into a partial update carrying the rows', () => { const change = refreshChange(); const changedRows = emptyChangedRows(); - convertToUpdateChange(change, changedRows); + markUpdateChange(change, changedRows); const updateChange = change as UpdateChange; expect(updateChange.changeType).toBe('update'); diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts index 17d5780dee7c..d93f3ef1175f 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/utils/row_changes.ts @@ -124,7 +124,7 @@ export function getRowOperation( return newItem ? 'replace' : undefined; } -export function createChangedRows(): ChangedRows { +export function initChangedRows(): ChangedRows { return { items: [], rowIndices: [], @@ -133,7 +133,7 @@ export function createChangedRows(): ChangedRows { }; } -function setChangedRows(change: UpdateChange, changedRows: ChangedRows): void { +function attachChangedRows(change: UpdateChange, changedRows: ChangedRows): void { change.rowIndices = changedRows.rowIndices; change.columnIndices = changedRows.columnIndices; change.changeTypes = changedRows.changeTypes; @@ -141,20 +141,20 @@ function setChangedRows(change: UpdateChange, changedRows: ChangedRows): void { } export function resetChangedRows(change: UpdateChange): ChangedRows { - const changedRows = createChangedRows(); + const changedRows = initChangedRows(); - setChangedRows(change, changedRows); + attachChangedRows(change, changedRows); return changedRows; } -export function convertToUpdateChange(change: DataChange, changedRows: ChangedRows): void { +export function markUpdateChange(change: DataChange, changedRows: ChangedRows): void { const updateChange = change as UpdateChange; updateChange.repaintChangesOnly = true; updateChange.changeType = 'update'; - setChangedRows(updateChange, changedRows); + attachChangedRows(updateChange, changedRows); } export function pushChangedRow(changedRows: ChangedRows, changedRow: UpdateRowChange): void { diff --git a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts index 2658803b6296..414de41e29c8 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts @@ -3175,10 +3175,9 @@ const editing = (Base: ModuleType) => class EditingController const data = (Base: ModuleType) => class DataControllerKeyboardExtender extends Base { protected correctRowIndices(getRowIndexCorrection) { - const that = this; const focusedCellPosition = this._keyboardNavigationController._focusedCellPosition; - super.correctRowIndices.apply(that, arguments as any); + super.correctRowIndices(getRowIndexCorrection); if (focusedCellPosition && focusedCellPosition.rowIndex >= 0) { const focusedRowIndexCorrection = getRowIndexCorrection(focusedCellPosition.rowIndex);