Skip to content

Commit 48b3bbd

Browse files
authored
T1260472: fix grid async render to avoid blinking (DevExpress#28975)
Co-authored-by: Vladimir Bushmanov <[email protected]>
1 parent 2f3ed8b commit 48b3bbd

File tree

6 files changed

+92
-2
lines changed

6 files changed

+92
-2
lines changed
16 KB
Loading
5.64 KB
Loading

e2e/testcafe-devextreme/tests/dataGrid/virtualColumns.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,86 @@ test('Group row should have right colspan with summary, virtual columns and fixe
348348
},
349349
});
350350
});
351+
352+
// T1260472
353+
test('Header, fixed columns and virtual scroll bar should have stable position during async render and virtual horizontal scrolling', async (t) => {
354+
const dataGrid = new DataGrid('#container');
355+
const { takeScreenshot, compareResults } = createScreenshotsComparer(t);
356+
357+
await t.expect(dataGrid.getDataRow(0).element.exists).ok(); // wait for initial render
358+
await ClientFunction(() => { (window as any).deferred = $.Deferred(); })();
359+
await dataGrid.scrollTo(t, { x: 2000 });
360+
await takeScreenshot('T1260472-async-render-during-horizontal-scrolling.png', dataGrid.element);
361+
await ClientFunction(() => {
362+
(window as any).deferred.resolve();
363+
(window as any).deferred = undefined;
364+
})();
365+
await takeScreenshot('T1260472-async-render-after-horizontal-scrolling.png', dataGrid.element);
366+
367+
await t
368+
.expect(compareResults.isValid())
369+
.ok(compareResults.errorMessages());
370+
}).before(async () => {
371+
const defaultColumnConfig = {
372+
headerCellTemplate: 'headerCellTemplate',
373+
cellTemplate: 'cellTemplate',
374+
};
375+
376+
return createWidget('dxDataGrid', {
377+
dataSource: generateData(3, 50),
378+
keyExpr: 'field1',
379+
showBorders: true,
380+
width: 500,
381+
height: 173,
382+
columnWidth: 100,
383+
scrolling: {
384+
rowRenderingMode: 'virtual',
385+
columnRenderingMode: 'virtual',
386+
mode: 'virtual',
387+
useNative: false,
388+
},
389+
columns: Array.from({ length: 20 }).map((_, i) => ({
390+
...defaultColumnConfig,
391+
caption: `Product${i + 1}`,
392+
fixed: i === 0,
393+
columns: [
394+
{ ...defaultColumnConfig, dataField: `field${(2 * i) + 1}`, fixed: i === 0 },
395+
{ ...defaultColumnConfig, dataField: `field${(2 * i) + 2}`, fixed: i === 0 },
396+
],
397+
})),
398+
// @ts-expect-error private option
399+
templatesRenderAsynchronously: true,
400+
integrationOptions: {
401+
templates: {
402+
headerCellTemplate: {
403+
render({ model, container, onRendered }) {
404+
const title = model.column.caption == null ? null : model.column.caption;
405+
const content = $(`<span title='${title}'>
406+
${title}
407+
</span>`);
408+
container.append(content);
409+
if ((window as any).deferred) {
410+
(window as any).deferred.done(onRendered);
411+
} else {
412+
onRendered();
413+
}
414+
},
415+
},
416+
cellTemplate: {
417+
render({ model, container, onRendered }) {
418+
const title = model.value == null ? null : model.value;
419+
const content = $(`<span title='${title}'>
420+
${title}
421+
</span>`);
422+
container.append(content);
423+
if ((window as any).deferred) {
424+
(window as any).deferred.done(onRendered);
425+
} else {
426+
onRendered();
427+
}
428+
},
429+
},
430+
},
431+
},
432+
});
433+
});

packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ export class FooterView extends ColumnsView {
226226
this._updateContent(this._renderTable({ change }), change);
227227
needUpdateScrollLeft && this._updateScrollLeftPosition();
228228
}
229+
230+
return super._renderCore(change);
229231
}
230232

231233
protected _updateContent($newTable, change) {

packages/devextreme/js/__internal/grids/grid_core/column_headers/m_column_headers.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ export class ColumnHeadersView extends ColumnsView {
299299

300300
$container
301301
.addClass(that.addWidgetPrefix(HEADERS_CLASS))
302-
.toggleClass(that.addWidgetPrefix(NOWRAP_CLASS), !that.option('wordWrapEnabled'))
303-
.empty();
302+
.toggleClass(that.addWidgetPrefix(NOWRAP_CLASS), !that.option('wordWrapEnabled'));
304303

305304
that.setAria('role', 'presentation', $container);
306305

packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,9 @@ export class ColumnsView extends ColumnStateMixin(modules.View) {
718718
if (!$root || $root.parent().length) {
719719
this.renderDelayedTemplates(e);
720720
}
721+
722+
// @ts-expect-error
723+
return new Deferred().resolve();
721724
}
722725

723726
/**
@@ -1108,6 +1111,9 @@ export class ColumnsView extends ColumnStateMixin(modules.View) {
11081111
return result.promise();
11091112
}
11101113

1114+
/**
1115+
* @extended: sticky_columns, rows_view
1116+
*/
11111117
protected _updateContent($newTableElement, change, isFixedTableRendering?) {
11121118
return this.waitAsyncTemplates().done(() => {
11131119
this._removeContent(isFixedTableRendering);

0 commit comments

Comments
 (0)