DevExtreme UI Component Suite
DevExtreme is an enterprise-ready JavaScript/TypeScript UI component suite offering a comprehensive collection of high-performance and responsive UI components for web development. It supports popular front-end frameworks including Angular, React, Vue, and jQuery. The current stable version is 25.2.6, released on April 7, 2026. DevExtreme maintains a consistent release cadence with two major versions annually (e.g., 25.1 and 25.2) and frequent patch updates for bug fixes and minor enhancements. Key differentiators include a vast array of widgets like DataGrid, TreeList, and various charts, alongside an integrated theming engine, client-side data management, and extensive globalization capabilities. It provides a unified API for a consistent developer experience across supported frameworks, abstracting underlying DOM complexities.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'dxDataGrid')
cause This error typically occurs when attempting to initialize a DevExtreme widget (like DataGrid) using jQuery syntax (e.g., `$(element).dxDataGrid(...)`) but the DevExtreme jQuery integration script or jQuery itself is not loaded, or the widget module is not imported correctly for modular setups.fixVerify that jQuery is included in your project and loaded before DevExtreme scripts. If using ES modules, ensure the specific widget is imported correctly, e.g., `import DataGrid from 'devextreme/ui/data_grid';`. If using framework wrappers, ensure the wrapper component is correctly imported and rendered. -
E1042 - The 'keyExpr' option is not specified for the DataGrid (or TreeList)
cause The DataGrid and TreeList components require a `keyExpr` (or `key` for ArrayStore) to uniquely identify data rows, which is crucial for internal operations like selection, editing, and state restoration.fixSet the `keyExpr` property in the DataGrid/TreeList configuration to the name of the field that uniquely identifies data objects (e.g., `keyExpr: 'id'`). If using a `DataSource` with an `ArrayStore`, specify the `key` option in the `ArrayStore` configuration. -
A request error occurs after filtering or searching (e.g., 'Query string is too long', '404.15')
cause When using server-side data processing with DevExtreme's `DataSource`, load parameters (filter, sort, skip, take) are sent via the URL query string. If the query string becomes excessively long, the server might reject the request due to URL length limits.fixConfigure your server to allow longer URL query strings. Alternatively, for large or complex filters, consider using the `POST` method for data requests, if supported by your data service, by configuring the `load` method of your `CustomStore` to send data in the request body instead of the URL. -
E4021 - CustomStore.load returns an undefined LoadResultObject.totalCount, or CustomStore.totalCount is not specified.
cause When implementing a `CustomStore` for server-side data, the `load` method's promise must resolve to an object containing `data` and `totalCount` properties. If `totalCount` is missing or undefined, this error occurs.fixEnsure that your `CustomStore`'s `load` method consistently returns an object with both `data` (the array of items) and `totalCount` (the total number of items, usually from the server response). If `totalCount` is not directly available from the server, you might need to fetch it separately or ensure the server-side logic provides it.
Warnings
- breaking Major version upgrades (e.g., v24 to v25) often introduce breaking changes in component APIs, configuration options, and internal structures. Always consult the official migration guides and release notes.
- breaking Since v23.2, a DevExtreme license key is required for commercial use. Failing to register it can lead to warnings or functionality issues in development environments.
- gotcha When using module bundlers like Webpack with Module Federation, issues can arise due to `instanceof` checks failing for DevExtreme data source classes, leading to unexpected errors. This occurs when multiple instances of the same DevExtreme module exist in the module graph.
- gotcha For non-framework (vanilla JavaScript) or jQuery-based usage, DevExtreme often relies on jQuery for its underlying DOM manipulation and widget initialization. Although modern framework wrappers abstract this, direct `devextreme` usage might implicitly expect jQuery to be available, leading to runtime errors if missing.
- deprecated DevExpress's custom NuGet server (`NuGet.DevExpress.com`) is being deprecated. While still operational for v25.1+, future versions (starting v26.1) will exclusively publish NuGet packages to `NuGet.org`.
Install
-
npm install devextreme -
yarn add devextreme -
pnpm add devextreme
Imports
- DataGrid
import { DataGrid } from 'devextreme';import DataGrid from 'devextreme/ui/data_grid';
- dx.light.css
import 'devextreme/dist/css/dx.light.css';
- locale
import * as localization from 'devextreme/localization';
import { locale, loadMessages } from 'devextreme/localization'; - dxButton
import { dxButton } from 'devextreme/ui/button';import Button from 'devextreme/ui/button';
Quickstart
import Button from 'devextreme/ui/button';
import DataGrid from 'devextreme/ui/data_grid';
import ArrayStore from 'devextreme/data/array_store';
import 'devextreme/dist/css/dx.light.css';
import 'devextreme/dist/css/dx.common.css';
document.addEventListener('DOMContentLoaded', () => {
const data = [
{ id: 1, firstName: 'John', lastName: 'Doe', city: 'New York' },
{ id: 2, firstName: 'Jane', lastName: 'Smith', city: 'London' },
{ id: 3, firstName: 'Peter', lastName: 'Jones', city: 'Paris' },
];
const buttonElement = document.createElement('div');
document.body.appendChild(buttonElement);
new Button(buttonElement, {
text: 'Click Me',
onClick: () => {
alert('Button clicked!');
},
});
const gridElement = document.createElement('div');
gridElement.style.marginTop = '20px';
document.body.appendChild(gridElement);
new DataGrid(gridElement, {
dataSource: new ArrayStore({
key: 'id',
data: data,
}),
columns: [
{ dataField: 'firstName', caption: 'First Name' },
{ dataField: 'lastName', caption: 'Last Name' },
{ dataField: 'city', caption: 'City' },
],
showBorders: true,
paging: {
pageSize: 5,
},
filterRow: {
visible: true,
applyFilter: 'auto',
},
headerFilter: {
visible: true,
},
});
});