diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/virtualColumns/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/virtualColumns/functional.ts index 2277f40a90f8..200b220ab8b5 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/virtualColumns/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/virtualColumns/functional.ts @@ -1,3 +1,4 @@ +import { ClientFunction } from 'testcafe'; import DataGrid from 'devextreme-testcafe-models/dataGrid'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; @@ -85,3 +86,74 @@ test('DataGrid should not scroll back to the focused cell after horizontal scrol columnRenderingMode: 'virtual', }, })); + +test('DataGrid with async templates should call load method only once on initial render', async (t) => { + const dataGrid = new DataGrid('#container'); + const getLoadCount = ClientFunction(() => (window as any).testLoadCount); + + await t.expect(dataGrid.isReady()).ok(); + + await t.expect(dataGrid.getDataCell(1000, 0).element.textContent).eql('1001 custom'); + + await t.expect(getLoadCount()).eql(1); +}).before(async () => createWidget('dxDataGrid', () => { + (window as any).testLoadCount = 0; + + const sampleAPI = new (window as any).DevExpress.data.ArrayStore({ + key: 'id', + data: Array.from({ length: 10000 }, (_, index) => ({ + id: index + 1, + text: `item long text ${index + 1}`, + })), + }); + + const store = new (window as any).DevExpress.data.CustomStore({ + key: 'id', + load(o: any) { + (window as any).testLoadCount += 1; + return new Promise((resolve) => { + setTimeout(() => { + sampleAPI.load(o).then(resolve); + }, 100); + }); + }, + totalCount(o: any) { + return sampleAPI.totalCount(o); + }, + }); + + return { + dataSource: store, + showBorders: true, + remoteOperations: true, + paging: { + pageSize: 100, + pageIndex: 10, + }, + scrolling: { + mode: 'virtual', + rowRenderingMode: 'virtual', + }, + columns: [ + { dataField: 'id', width: 90, cellTemplate: 'myTemplate' }, + { dataField: 'text', width: 150 }, + ], + height: 1500, + wordWrapEnabled: true, + templatesRenderAsynchronously: true, + integrationOptions: { + templates: { + myTemplate: { + render(e: any) { + setTimeout(() => { + $('
').text(`${e.model.text} custom`).appendTo(e.container); + e.onRendered?.(); + }, 100); + }, + }, + }, + }, + }; +})).after(async () => ClientFunction(() => { + delete (window as any).testLoadCount; +})()); 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 5a30993d5fa6..212dabc4d8f1 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 @@ -1440,6 +1440,9 @@ export const rowsView = (Base: ModuleType) => class VirtualScrollingRo public renderDelayedTemplates() { this.waitAsyncTemplates().done(() => { this._updateContentPosition(true); + if (this.option(LEGACY_SCROLLING_MODE) === false) { + this._updateViewportSize(getOuterHeight(this.element()), this._scrollTop); + } }); super.renderDelayedTemplates.apply(this, arguments as any); }