Skip to content

Commit c438faa

Browse files
author
Alyar
committed
Fix T1292991
1 parent 15a4cab commit c438faa

3 files changed

Lines changed: 106 additions & 52 deletions

File tree

e2e/testcafe-devextreme/tests/dataGrid/common/focus/focusedRow/focusedRow.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,3 +987,56 @@ test('Group should expand when focusedRowKey is set and data items have \'items\
987987
height: 400,
988988
focusedRowEnabled: true,
989989
}));
990+
991+
// T1292991
992+
test('Focused row index should be updated after updating a row when repaintChangesOnly is enabled', async (t) => {
993+
// arrange
994+
const dataGrid = new DataGrid('#container');
995+
const updateThirdRowData = ClientFunction(() => {
996+
(window as any).widget.getDataSource().store().push([
997+
{
998+
type: 'update',
999+
key: 3,
1000+
data: { id: 3, name: 'A Item 3' },
1001+
},
1002+
]);
1003+
});
1004+
1005+
// assert
1006+
await t
1007+
.expect(dataGrid.option('focusedRowKey'))
1008+
.eql(2)
1009+
.expect(dataGrid.option('focusedRowIndex'))
1010+
.eql(1);
1011+
1012+
// act
1013+
await updateThirdRowData();
1014+
1015+
// assert
1016+
await t
1017+
.expect(dataGrid.option('focusedRowKey'))
1018+
.eql(2)
1019+
.expect(dataGrid.option('focusedRowIndex'))
1020+
.eql(2);
1021+
}).before(async () => createWidget('dxDataGrid', {
1022+
dataSource: {
1023+
store: {
1024+
type: 'array',
1025+
data: [
1026+
{ id: 1, name: 'Item 1' },
1027+
{ id: 2, name: 'Item 2' },
1028+
{ id: 3, name: 'Item 3' },
1029+
],
1030+
key: 'id',
1031+
},
1032+
reshapeOnPush: true,
1033+
},
1034+
showBorders: true,
1035+
focusedRowEnabled: true,
1036+
focusedRowKey: 2,
1037+
repaintChangesOnly: true,
1038+
columns: [
1039+
{ dataField: 'id', width: 80 },
1040+
{ dataField: 'name', caption: 'Name', sortOrder: 'asc' },
1041+
],
1042+
}));

packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -84,30 +84,18 @@ export class FocusController extends core.ViewController {
8484
if (!this.option('focusedRowEnabled')) {
8585
return;
8686
}
87-
const isEmptyData = this.getDataController().isEmpty();
88-
const currentIndex = this._getCurrentFocusRowIndex(isEmptyData, index);
87+
88+
const currentIndex = index !== undefined ? index : this.option('focusedRowIndex');
8989

9090
if (currentIndex < 0) {
91-
if (isEmptyData || this.isAutoNavigateToFocusedRow()) {
91+
if (this.isAutoNavigateToFocusedRow()) {
9292
this._resetFocusedRow();
9393
}
9494
} else {
9595
this._focusRowByIndexCore(currentIndex, operationTypes);
9696
}
9797
}
9898

99-
private _getCurrentFocusRowIndex(isEmptyData, index?): number {
100-
let currentIndex = index;
101-
if (currentIndex === undefined) {
102-
if (isEmptyData) {
103-
currentIndex = -1;
104-
} else {
105-
currentIndex = this.option('focusedRowIndex');
106-
}
107-
}
108-
return currentIndex;
109-
}
110-
11199
private _focusRowByIndexCore(index, operationTypes) {
112100
const pageSize = this.getDataController().pageSize();
113101
const setKeyByIndex = () => {
@@ -560,7 +548,7 @@ const columns = (Base: ModuleType<ColumnsController>) => class FocusColumnsExten
560548
};
561549

562550
const data = (Base: ModuleType<DataController>) => class FocusDataControllerExtender extends Base {
563-
private _needToUpdateFocusedRowByIndex = false;
551+
private _isDataPushed = false;
564552

565553
protected _applyChange(change) {
566554
if (change && change.changeType === 'updateFocusedRow') return;
@@ -572,20 +560,23 @@ const data = (Base: ModuleType<DataController>) => class FocusDataControllerExte
572560
protected _fireChanged(e) {
573561
super._fireChanged(e);
574562

563+
const forceUpdateFocusedRow = this._isDataPushed;
564+
565+
this._isDataPushed = false;
566+
575567
if (this.option('focusedRowEnabled') && this._dataSource) {
576568
const isPartialUpdate = e.changeType === 'update' && e.repaintChangesOnly;
577569
const isPartialUpdateWithDeleting = isPartialUpdate && e.changeTypes && e.changeTypes.indexOf('remove') >= 0;
578570

579-
if (this._needToUpdateFocusedRowByIndex) {
580-
this._needToUpdateFocusedRowByIndex = false;
581-
this._focusController._focusRowByIndex();
571+
if (forceUpdateFocusedRow && this.isEmpty()) {
572+
this._focusController._resetFocusedRow();
582573
} else if (e.changeType === 'refresh' && e.items.length || isPartialUpdateWithDeleting) {
583574
this._updatePageIndexes();
584-
this._updateFocusedRow(e);
575+
this._updateFocusedRowIfNeeded(e, forceUpdateFocusedRow);
585576
} else if (e.changeType === 'append' || e.changeType === 'prepend') {
586577
this._updatePageIndexes();
587-
} else if (e.changeType === 'update' && e.repaintChangesOnly) {
588-
this._updateFocusedRow(e);
578+
} else if (isPartialUpdate) {
579+
this._updateFocusedRowIfNeeded(e, forceUpdateFocusedRow);
589580
}
590581
}
591582
}
@@ -595,7 +586,7 @@ const data = (Base: ModuleType<DataController>) => class FocusDataControllerExte
595586

596587
const focusedRowKey = this.option('focusedRowKey');
597588

598-
this._needToUpdateFocusedRowByIndex = changes?.some((change) => change.type === 'remove' && equalByValue(change.key, focusedRowKey));
589+
this._isDataPushed = isDefined(focusedRowKey) && !!changes.length;
599590
}
600591

601592
private _updatePageIndexes() {
@@ -610,7 +601,7 @@ const data = (Base: ModuleType<DataController>) => class FocusDataControllerExte
610601
return this._isPagingByRendering;
611602
}
612603

613-
private _updateFocusedRow(e) {
604+
private _updateFocusedRowIfNeeded(e, forceUpdate = false) {
614605
const operationTypes = e.operationTypes || {};
615606
const {
616607
reload, fullReload, pageIndex, paging,
@@ -620,30 +611,44 @@ const data = (Base: ModuleType<DataController>) => class FocusDataControllerExte
620611
const focusedRowKey = this.option('focusedRowKey');
621612
const isAutoNavigate = this._focusController.isAutoNavigateToFocusedRow();
622613
const isReload = reload && pageIndex === false;
623-
if (isReload && !fullReload && isDefined(focusedRowKey)) {
624-
this._focusController._navigateToRow(focusedRowKey, true)
625-
.done((focusedRowIndex) => {
626-
if (focusedRowIndex < 0) {
627-
this._focusController._focusRowByIndex(undefined, operationTypes);
628-
}
629-
});
630-
} else if (pagingWithoutVirtualScrolling && isAutoNavigate) {
631-
const rowIndexByKey = this.getRowIndexByKey(focusedRowKey);
632-
const focusedRowIndex = this.option('focusedRowIndex')!;
633-
const isValidRowIndexByKey = rowIndexByKey >= 0;
634-
const isValidFocusedRowIndex = focusedRowIndex >= 0;
635-
const isSameRowIndex = focusedRowIndex === rowIndexByKey;
636-
if (isValidFocusedRowIndex && (isSameRowIndex || !isValidRowIndexByKey)) {
637-
this._focusController._focusRowByIndex(focusedRowIndex, operationTypes);
614+
const rowIndexByKey = this.getRowIndexByKey(focusedRowKey);
615+
616+
switch (true) {
617+
case forceUpdate: {
618+
this._focusController._focusRowByKeyOrIndex();
619+
break;
620+
}
621+
case isReload && !fullReload && isDefined(focusedRowKey): {
622+
this._focusController._navigateToRow(focusedRowKey, true)
623+
.done((focusedRowIndex) => {
624+
if (focusedRowIndex < 0) {
625+
this._focusController._focusRowByIndex(undefined, operationTypes);
626+
}
627+
});
628+
break;
629+
}
630+
case pagingWithoutVirtualScrolling && isAutoNavigate: {
631+
const focusedRowIndex = this.option('focusedRowIndex')!;
632+
const isValidRowIndexByKey = rowIndexByKey >= 0;
633+
const isValidFocusedRowIndex = focusedRowIndex >= 0;
634+
const isSameRowIndex = focusedRowIndex === rowIndexByKey;
635+
636+
if (isValidFocusedRowIndex && (isSameRowIndex || !isValidRowIndexByKey)) {
637+
this._focusController._focusRowByIndex(focusedRowIndex, operationTypes);
638+
}
639+
break;
640+
}
641+
case pagingWithoutVirtualScrolling && !isAutoNavigate && (rowIndexByKey < 0): {
642+
this.option('focusedRowIndex', -1);
643+
break;
644+
}
645+
case operationTypes.fullReload: {
646+
this._focusController._focusRowByKeyOrIndex();
647+
break;
648+
}
649+
default: {
650+
break;
638651
}
639-
} else if (
640-
pagingWithoutVirtualScrolling
641-
&& !isAutoNavigate
642-
&& (this.getRowIndexByKey(focusedRowKey) < 0)
643-
) {
644-
this.option('focusedRowIndex', -1);
645-
} else if (operationTypes.fullReload) {
646-
this._focusController._focusRowByKeyOrIndex();
647652
}
648653
}
649654

packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,11 +2781,7 @@ const rowsView = (Base: ModuleType<RowsView>) => class RowsViewKeyboardExtender
27812781
const { operationTypes, repaintChangesOnly } = change ?? {};
27822782
const { fullReload, pageSize } = operationTypes ?? {};
27832783

2784-
const hasInsertsOrRemoves = !!change?.changeTypes?.find(
2785-
(changeType) => changeType === 'insert' || changeType === 'remove',
2786-
);
2787-
2788-
if (!change || !repaintChangesOnly || fullReload || pageSize || hasInsertsOrRemoves) {
2784+
if (!change || !repaintChangesOnly || fullReload || pageSize) {
27892785
const preventScroll = shouldPreventScroll(this);
27902786
this.renderFocusState({
27912787
preventScroll,

0 commit comments

Comments
 (0)