Feel free to share demo-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Backend API
import React, { useCallback, useState } from 'react';
import DataGrid, {
Scrolling, Sorting, LoadPanel, type DataGridTypes,
} from 'devextreme-react/data-grid';
import { generateData } from './data.ts';
const dataSource = generateData(100000);
const customizeColumns = (columns: DataGridTypes.Column[]) => {
columns[0].width = 70;
};
const App = () => {
const [loadPanelEnabled, setLoadPanelEnabled] = useState(true);
const onContentReady = useCallback(() => {
setLoadPanelEnabled(false);
}, []);
return (
<DataGrid
height={440}
dataSource={dataSource}
keyExpr="id"
showBorders={true}
customizeColumns={customizeColumns}
onContentReady={onContentReady}
>
<Sorting mode="none" />
<Scrolling mode="virtual" />
<LoadPanel enabled={loadPanelEnabled} />
</DataGrid>
);
};
export default App;
import React, { useCallback, useState } from 'react';
import DataGrid, { Scrolling, Sorting, LoadPanel } from 'devextreme-react/data-grid';
import { generateData } from './data.js';
const dataSource = generateData(100000);
const customizeColumns = (columns) => {
columns[0].width = 70;
};
const App = () => {
const [loadPanelEnabled, setLoadPanelEnabled] = useState(true);
const onContentReady = useCallback(() => {
setLoadPanelEnabled(false);
}, []);
return (
<DataGrid
height={440}
dataSource={dataSource}
keyExpr="id"
showBorders={true}
customizeColumns={customizeColumns}
onContentReady={onContentReady}
>
<Sorting mode="none" />
<Scrolling mode="virtual" />
<LoadPanel enabled={loadPanelEnabled} />
</DataGrid>
);
};
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
let s = 123456789;
function random() {
s = (1103515245 * s + 12345) % 2147483647;
return s % (10 - 1);
}
export function generateData(count: number) {
let i;
const surnames = ['Smith', 'Johnson', 'Brown', 'Taylor', 'Anderson', 'Harris', 'Clark', 'Allen', 'Scott', 'Carter'];
const names = ['James', 'John', 'Robert', 'Christopher', 'George', 'Mary', 'Nancy', 'Sandra', 'Michelle', 'Betty'];
const gender = ['Male', 'Female'];
const items: ({ id: number; firstName: string; lastName: string; gender: string; birthDate: Date; })[] = [];
const startBirthDate = Date.parse('1/1/1975');
const endBirthDate = Date.parse('1/1/1992');
for (i = 0; i < count; i += 1) {
const birthDate = new Date(startBirthDate + Math.floor(
(random() * (endBirthDate - startBirthDate)) / 10,
));
birthDate.setHours(12);
const nameIndex = random();
const item = {
id: i + 1,
firstName: names[nameIndex],
lastName: surnames[random()],
gender: gender[Math.floor(nameIndex / 5)],
birthDate,
};
items.push(item);
}
return items;
}
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://cdn.jsdelivr.net/npm/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@25.1.3/cjs',
'devextreme-react': 'npm:devextreme-react@25.1.3/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.3/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.19/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.62/dist/dx-gantt.js',
'inferno': 'npm:inferno@8.2.3/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@8.2.3/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'@preact/signals-core': 'npm:@preact/signals-core@1.8.0/dist/signals-core.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme-react/common': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/common/core/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
let s = 123456789;
function random() {
s = (1103515245 * s + 12345) % 2147483647;
return s % (10 - 1);
}
export function generateData(count) {
let i;
const surnames = [
'Smith',
'Johnson',
'Brown',
'Taylor',
'Anderson',
'Harris',
'Clark',
'Allen',
'Scott',
'Carter',
];
const names = [
'James',
'John',
'Robert',
'Christopher',
'George',
'Mary',
'Nancy',
'Sandra',
'Michelle',
'Betty',
];
const gender = ['Male', 'Female'];
const items = [];
const startBirthDate = Date.parse('1/1/1975');
const endBirthDate = Date.parse('1/1/1992');
for (i = 0; i < count; i += 1) {
const birthDate = new Date(
startBirthDate + Math.floor((random() * (endBirthDate - startBirthDate)) / 10),
);
birthDate.setHours(12);
const nameIndex = random();
const item = {
id: i + 1,
firstName: names[nameIndex],
lastName: surnames[random()],
gender: gender[Math.floor(nameIndex / 5)],
birthDate,
};
items.push(item);
}
return items;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/25.1.3/css/dx.light.css" />
<script src="https://cdn.jsdelivr.net/npm/core-js@2.6.12/client/shim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@0.21.3/dist/system.js"></script>
<script type="text/javascript" src="config.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script type="text/javascript">
System.import("./index.tsx");
</script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
Unlike infinite scrolling, virtual scrolling allows users to navigate to any section of rows immediately. DataGrid only loads displayed rows into memory and unloads rows as they are hidden by user scrolling. When virtual scrolling is enabled, Ctrl+Home and Ctrl+End focus the first cell in the first row/last cell in the last row of the component data set.