React DataGrid - Getting Started
DevExtreme includes multiple data management components. You can use them to display tabular, hierarchical, multidimensional data, or present information as cards. For more information about these components and their features, see How to Choose a Data Management Component.
jQuery
Angular
Vue
React
The DataGrid component displays data from a local or remote store and allows users to sort, group, filter, and perform other operations on columns and records.
Need to create printable documents simply? Try our .NET-based DevExpress Reports: they ship with an intuitive Visual Studio Report Designer, Web Report Designer for end-user ad-hoc reporting, and a rich set of report controls, including cross tabs and charts.
You can generate a variety of report types — from simple mail-merge, table, and vertical reports to master-detail (hierarchical) and cross-tab reports, print or export them to PDF, Excel, and other formats.
Develop using VS Code? Leverage the capabilities of a brand new VS Code Report Designer extension to create and edit reports/documents on any platform, be it Windows, macOS, or Linux.
Get Started with DevExpress Reports | Explore Demos
Use our DevExpress BI Dashboard to embed interactive business intelligence into your next web app.
The Web Dashboard is a data analysis UI component that you can embed into your ASP.NET Core or Angular, React, and Vue applications with .NET backend. Dashboards allow you to display multiple inter-connected data analysis elements such as grids, charts, maps, gauges, and others: all within an automatically-arranged layout.
The set of components allows you to deploy an all-in-one solution and switch between Viewer and Designer modes directly on the web client (includes adaptive layouts for tablet & mobile).
The Web Dashboard is available as a part of a Universal subscription.
This tutorial shows how to add the DataGrid to a page, bind it to data, and configure its core features. As a result, you will get a UI component that looks as follows:
Each section in this tutorial covers a single configuration step. You can also find the full code in the GitHub repository.
Create a DataGrid
jQuery
Add DevExtreme to your jQuery application and use the following code to create a DataGrid:
Angular
Add DevExtreme to your Angular application and use the following code to create a DataGrid:
Vue
Add DevExtreme to your Vue application and use the following code to create a DataGrid:
React
Add DevExtreme to your React application and use the following code to create a DataGrid:
jQuery
$(function() {
$("#dataGrid").dxDataGrid({
// Configuration goes here
});
});
<html>
<head>
<!-- ... -->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/26.1.4/css/dx.light.css">
<link rel="stylesheet" href="index.css">
<script type="text/javascript" src="https://cdn3.devexpress.com/jslib/26.1.4/js/dx.all.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body class="dx-viewport">
<div id="dataGrid"></div>
</body>
</html>
#dataGrid {
height: 500px;
}ASP.NET Core Controls
@(Html.DevExtreme().DataGrid()
.ID("grid-container")
)
#grid-container {
height: 500px;
}Angular
<dx-data-grid id="dataGrid"
<!-- Configuration goes here -->
>
</dx-data-grid>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { DxDataGridModule } from 'devextreme-angular';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
DxDataGridModule
],
providers: [ ],
bootstrap: [AppComponent]
})
export class AppModule { }
#dataGrid {
height: 500px;
}Vue
<template>
<div id="app-container">
<DxDataGrid id="dataGrid">
<!-- Configuration goes here -->
</DxDataGrid>
</div>
</template>
<script>
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DxDataGrid } from 'devextreme-vue/data-grid';
export default {
components: {
DxDataGrid
}
}
</script>
<style>
#dataGrid {
height: 500px;
}
</style>React
import React from 'react';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DataGrid } from 'devextreme-react/data-grid';
function App() {
return (
<div className="App">
<DataGrid id="dataGrid">
{/* Configuration goes here */}
</DataGrid>
</div>
);
}
export default App;
#dataGrid {
height: 500px;
}Bind the DataGrid to Data
DataGrid can load and update data from different data source types. To use a local array, assign the array to dataSource and specify the key field in keyExpr.
The following code snippet initializes a DataGrid and creates columns for all data fields. All columns are equal width, and the column order follows the data source structure.
jQuery
$(function() {
$("#dataGrid").dxDataGrid({
dataSource: employees,
keyExpr: "EmployeeID",
});
});
const employees = [
// ...
];ASP.NET Core Controls
@using ASP_NET_Core.Models
@(Html.DevExtreme().DataGrid<Employee>()
.ID("grid-container")
.DataSource(d => d
.Mvc().Controller("EmployeeData")
.LoadAction("Get")
.Key("EmployeeID")
)
)
using ASP_NET_Core.Models;
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace ASP_NET_Core.Controllers;
public class EmployeeDataController : Controller {
[HttpGet]
public object Get(DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(EmployeeData.Employees, loadOptions);
}
}
namespace ASP_NET_Core.Models;
public class Employee {
public int EmployeeID { get; set; }
public string FullName { get; set; }
public string Position { get; set; }
public string TitleOfCourtesy { get; set; }
public string BirthDate { get; set; }
public string HireDate { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string HomePhone { get; set; }
public string Extension { get; set; }
public string Photo { get; set; }
public string Notes { get; set; }
public int? ReportsTo { get; set; }
}
namespace ASP_NET_Core.Models;
static class EmployeeData {
public static List<Employee> Employees = [
// ...
];
}Angular
<dx-data-grid
[dataSource]="employees"
keyExpr="EmployeeID">
</dx-data-grid>
import { Component } from '@angular/core';
import { Employee, EmployeesService } from './employees.service';
// ...
export class AppComponent {
employees: Employee[] = [];
constructor(service: EmployeesService) {
this.employees = service.getEmployees();
}
}
import { Injectable } from '@angular/core';
export interface Employee {
EmployeeID: number;
FullName: string;
Position: string;
TitleOfCourtesy: string;
BirthDate: string;
HireDate: string;
Address: string;
City: string;
Region: string;
PostalCode: string;
Country: string;
HomePhone: string;
Extension: string;
Photo: string;
Notes: string;
ReportsTo: number | null;
}
const employees: Employee[] = [
// ...
];
@Injectable({
providedIn: 'root'
})
export class EmployeesService {
getEmployees(): Employee[] {
return employees;
}
}Vue
<template>
<div id="app-container">
<DxDataGrid
:data-source="employees"
key-expr="EmployeeID">
</DxDataGrid>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { getEmployees, type Employee } from './employees.service';
const employees = ref<Employee[]>(getEmployees());
</script>
export interface Employee {
EmployeeID: number;
FullName: string;
Position: string;
TitleOfCourtesy: string;
BirthDate: string;
HireDate: string;
Address: string;
City: string;
Region: string | null;
PostalCode: string;
Country: string;
HomePhone: string;
Extension: string;
Photo: string;
Notes: string;
ReportsTo: number | null;
}
const employees = [
// ...
];
export function getEmployees(): Employee[] {
return employees;
}React
// ...
import { employees } from './employees';
function App() {
return (
<div className="App">
<DataGrid
dataSource={employees}
keyExpr="EmployeeID">
</DataGrid>
</div>
);
}
export interface Employee {
EmployeeID: number;
FullName: string;
Position: string;
TitleOfCourtesy: string;
BirthDate: string;
HireDate: string;
Address: string;
City: string;
Region: string | null;
PostalCode: string;
Country: string;
HomePhone: string;
Extension: string;
Photo: string;
Notes: string;
ReportsTo: number | null;
}
export const employees = [
// ...
];To use another data source type, refer to the following help topics:
Customize Columns
Read Tutorial: Columns - Overview
jQuery
Use the columns array to define and customize DataGrid columns. Configure columns as objects to specify options. To add columns with default options, add dataField values to columns[] as strings.
Angular
Specify the columns array to define and customize DataGrid columns. Specify each column's dataField value.
Vue
Specify the columns array to define and customize DataGrid columns. To add a column, specify the dataField value.
React
Specify the columns array to define and customize DataGrid columns. To add a column, specify the dataField value.
Reorder Columns
Read Tutorial: Column Reordering
To set the initial column order, arrange items in the columns[] array as needed. Enable allowColumnReordering to allow users to reorder columns in the component UI.
The following code snippet also specifies dataType for BirthDate and HireDate columns to display string values as dates:
jQuery
$("#dataGrid").dxDataGrid({
columns: [{
dataField: "FullName"
}, {
dataField: "Position"
}, {
dataField: "BirthDate",
dataType: "date",
}, {
dataField: "HireDate",
dataType: "date",
},"City", {
dataField: "Country"
},
"Address",
"HomePhone",
{
dataField: "PostalCode",
}],
allowColumnReordering: true,
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.Columns(columns => {
columns.AddFor(m => m.FullName);
columns.AddFor(m => m.Position);
columns.AddFor(m => m.BirthDate)
.DataType(GridColumnDataType.Date);
columns.AddFor(m => m.HireDate)
.DataType(GridColumnDataType.Date);
columns.AddFor(m => m.Country);
columns.AddFor(m => m.Address);
columns.AddFor(m => m.HomePhone);
columns.AddFor(m => m.PostalCode);
})
@* ... *@
)Angular
<dx-data-grid [allowColumnReordering]="true">
<dxi-data-grid-column dataField="FullName"></dxi-data-grid-column>
<dxi-data-grid-column dataField="Position"></dxi-data-grid-column>
<dxi-data-grid-column
dataField="BirthDate"
dataType="date">
</dxi-data-grid-column>
<dxi-data-grid-column
dataField="HireDate"
dataType="date">
</dxi-data-grid-column>
<dxi-data-grid-column dataField="City"></dxi-data-grid-column>
<dxi-data-grid-column dataField="Country"></dxi-data-grid-column>
<dxi-data-grid-column dataField="Address"></dxi-data-grid-column>
<dxi-data-grid-column dataField="HomePhone"></dxi-data-grid-column>
<dxi-data-grid-column dataField="PostalCode"></dxi-data-grid-column>
</dx-data-grid>Vue
<template>
<DxDataGrid :allow-column-reordering="true">
<DxColumn data-field="FullName"></DxColumn>
<DxColumn data-field="Position"></DxColumn>
<DxColumn
data-field="BirthDate"
data-type="date">
</DxColumn>
<DxColumn
data-field="HireDate"
data-type="date">
</DxColumn>
<DxColumn data-field="City" />
<DxColumn data-field="Country"></DxColumn>
<DxColumn data-field="Address" />
<DxColumn data-field="HomePhone" />
<DxColumn data-field="PostalCode" />
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, Column } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid allowColumnReordering={true}>
<Column dataField="FullName"></Column>
<Column dataField="Position"></Column>
<Column
dataField="BirthDate"
dataType="date">
</Column>
<Column
dataField="HireDate"
dataType="date">
</Column>
<Column dataField="City" />
<Column dataField="Country"></Column>
<Column dataField="Address" />
<Column dataField="HomePhone" />
<Column dataField="PostalCode" />
</DataGrid>
);
}Resize Columns
DataGrid columns have equal widths in the default configuration (width is set to "auto"). To change the column layout, you can define each column's width property or enable columnAutoWidth to adjust all columns to fit cell values. To allow users to change the column layout, enable allowColumnResizing.
jQuery
$("#dataGrid").dxDataGrid({
allowColumnResizing: true,
columnAutoWidth: true,
columns: [{
dataField: "BirthDate",
dataType: "date",
width: 100,
}, {
dataField: "HireDate",
dataType: "date",
width: 100,
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.AllowColumnResizing(true)
.ColumnAutoWidth(true)
.Columns(columns => {
columns.AddFor(m => m.BirthDate)
.DataType(GridColumnDataType.Date)
.Width(100);
columns.AddFor(m => m.HireDate)
.DataType(GridColumnDataType.Date)
.Width(100);
})
@* ... *@
)Angular
<dx-data-grid
[allowColumnResizing]="true"
[columnAutoWidth]="true"
>
<dxi-data-grid-column
dataField="BirthDate"
dataType="date"
[width]="100"
></dxi-data-grid-column>
<dxi-data-grid-column
dataField="HireDate"
dataType="date"
[width]="100"
></dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid
:allow-column-resizing="true"
:column-auto-width="true"
>
<DxColumn
data-field="BirthDate"
data-type="date"
:width="100"
/>
<DxColumn
data-field="HireDate"
data-type="date"
:width="100"
/>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, Column } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid
columnAutoWidth={true}
allowColumnResizing={true}
>
<Column
dataField="BirthDate"
dataType="date"
width={100}
/>
<Column
dataField="HireDate"
dataType="date"
width={100}
/>
{/* ... */}
</DataGrid>
);
}Fix Columns
When the total column width exceeds the UI component width, a horizontal scroll bar appears. To keep specific columns visible, enable columnFixing. Set columns[].fixed to true to fix a column. Set fixedPosition to specify the fixed column position or create a sticky column. Users can also change column fixing options in the DataGrid context menu.
jQuery
$("#dataGrid").dxDataGrid({
columnFixing: { enabled: true },
columns: [{
dataField: "FullName",
fixed: true
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.ColumnFixing(c => c.Enabled(true))
.Columns(columns => {
columns.AddFor(m => m.FullName)
.Fixed(true);
})
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-column-fixing [enabled]="true"></dxo-data-grid-column-fixing>
<dxi-data-grid-column
dataField="FullName"
[fixed]="true"
></dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid>
<DxColumnFixing :enabled="true" />
<DxColumn
data-field="FullName"
:fixed="true"
/>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxColumnFixing, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, ColumnFixing, Column } from 'devextreme-react/data-grid';
function App() {
return (
<div className="App">
<DataGrid>
<ColumnFixing enabled={true} />
<Column
dataField="FullName"
fixed={true}
/>
{/* ... */}
</DataGrid>
</div>
);
}Hide Columns
Read Tutorial: Hide a Column Using the API Read Tutorial: Column Chooser
To hide a DataGrid column, set columns[].visible to false. If the columnChooser is enabled, users can restore hidden columns. To hide a column in both the component and the column chooser, omit the corresponding columns[] item.
jQuery
$("#dataGrid").dxDataGrid({
columnChooser: { enabled: true },
columns: [{
dataField: "PostalCode",
visible: false
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.ColumnChooser(c => c.Enabled(true))
.Columns(columns => {
columns.AddFor(m => m.PostalCode)
.Visible(false);
})
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-column-chooser [enabled]="true"></dxo-data-grid-column-chooser>
<dxi-data-grid-column
dataField="PostalCode"
[visible]="false"
></dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid ... >
<DxColumnChooser :enabled="true" />
<DxColumn
data-field="PostalCode"
:visible="false"
/>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxColumnChooser, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, ColumnChooser, Column } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid ... >
<ColumnChooser enabled={true} />
<Column
dataField="PostalCode"
visible={false}
/>
{/* ... */}
</DataGrid>
);
}Sort Data
Read Tutorial: DataGrid - Sorting
The sorting.mode property specifies whether users can sort grid records against single or multiple columns.
You can also set a column's sortOrder and sortIndex properties to specify initial sorting settings. sortIndex applies only in multi-column sort mode.
To sort data and change sort orders in the UI, click column headers. Hold Shift and click to sort data against multiple columns.
jQuery
$("#dataGrid").dxDataGrid({
sorting: { mode: "multiple" },
columns: [{
dataField: "Country",
sortOrder: "asc",
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.Sorting(s => s.Mode(GridSortingMode.Multiple))
.Columns(columns => {
columns.AddFor(m => m.Country)
.SortOrder(SortOrder.Asc);
})
@* ... *@
)Angular
<dx-data-grid>
<dxo-sorting mode="multiple"></dxo-sorting>
<dxi-data-grid-column
dataField="Country"
sortOrder="asc"
></dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid ... >
<DxSorting mode="multiple" />
<DxColumn
data-field="Country"
sort-order="asc"
/>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxSorting, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, Sorting, Column } from 'devextreme-react/data-grid';
function App() {
return (
<div className="App">
<DataGrid ... >
<Sorting mode="multiple" />
<Column
dataField="Country"
sortOrder="asc"
/>
{/* ... */}
</DataGrid>
</div>
);
}Filter and Search Data
Read Tutorial: DataGrid - Filtering and Searching
DataGrid includes the following UI elements used to filter and search data:
This tutorial uses the filterRow and searchPanel:
jQuery
$("#dataGrid").dxDataGrid({
filterRow: { visible: true },
searchPanel: { visible: true },
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.FilterRow(f => f.Visible(true))
.SearchPanel(s => s.Visible(true))
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-filter-row [visible]="true"></dxo-data-grid-filter-row>
<dxo-data-grid-search-panel [visible]="true"></dxo-data-grid-search-panel>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid ... >
<DxFilterRow :visible="true" />
<DxSearchPanel :visible="true" />
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxFilterRow, DxSearchPanel } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, FilterRow, SearchPanel } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid ... >
<FilterRow visible={true} />
<SearchPanel visible={true} />
{/* ... */}
</DataGrid>
);
}Group Data
Read Tutorial: DataGrid - Grouping
You can group DataGrid records against single or multiple columns. To group records in the UI, right-click column headers if grouping.contextMenuEnabled is true (default). You can also drag and drop column headers onto the group panel if groupPanel.visible is true.
To group data in code, define columns[].groupIndex property. This tutorial specifies groupIndex for the Country column:
jQuery
$("#dataGrid").dxDataGrid({
groupPanel: { visible: true },
columns: [{
dataField: "Country",
groupIndex: 0,
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.GroupPanel(p => p.Visible(true))
.Columns(columns => {
columns.AddFor(m => m.Country)
.GroupIndex(0);
})
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-group-panel [visible]="true"></dxo-data-grid-group-panel>
<dxi-data-grid-column
dataField="Country"
[groupIndex]="0"
></dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid>
<DxGroupPanel :visible="true" />
<DxColumn
data-field="Country"
:group-index="0"
/>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxGroupPanel, DxColumn } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, GroupPanel, Column } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid>
<GroupPanel visible={true} />
<Column
dataField="Country"
groupIndex={0}
/>
{/* ... */}
</DataGrid>
);
}Edit and Validate Data
Read Tutorial: DataGrid - Editing
Users can add new records and update or delete existing records. To allow these operations, enable the following editing options:
DataGrid supports multiple edit modes. This tutorial uses the pop-up edit mode.
This tutorial also implements data validation to check that edited data is valid before saving. Required rules are configured to ensure certain column values are never empty:
jQuery
$("#dataGrid").dxDataGrid({
editing: {
mode: "popup",
allowUpdating: true,
allowDeleting: true,
allowAdding: true
},
columns: [{
dataField: "FullName",
validationRules: [{ type: "required" }]
}, {
dataField: "Position",
validationRules: [{ type: "required" }]
}, {
dataField: "BirthDate",
validationRules: [{ type: "required" }]
}, {
dataField: "HireDate",
validationRules: [{ type: "required" }]
}, {
dataField: "Country",
validationRules: [{ type: "required" }]
}, /* ... */ ],
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.Editing(e => e
.Mode(GridEditMode.Popup)
.AllowAdding(true)
.AllowDeleting(true)
.AllowUpdating(true)
)
.Columns(columns => {
columns.AddFor(m => m.FullName)
.ValidationRules(v => v.AddRequired());
columns.AddFor(m => m.Position)
.ValidationRules(v => v.AddRequired());
columns.AddFor(m => m.BirthDate)
.ValidationRules(v => v.AddRequired());
columns.AddFor(m => m.HireDate)
.ValidationRules(v => v.AddRequired());
columns.AddFor(m => m.Country)
.ValidationRules(v => v.AddRequired());
})
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-editing
mode="popup"
[allowUpdating]="true"
[allowDeleting]="true"
[allowAdding]="true"
></dxo-data-grid-editing>
<dxi-data-grid-column dataField="FullName">
<dxi-data-grid-validation-rule type="required"></dxi-data-grid-validation-rule>
</dxi-data-grid-column>
<dxi-data-grid-column dataField="Position">
<dxi-data-grid-validation-rule type="required"></dxi-data-grid-validation-rule>
</dxi-data-grid-column>
<dxi-data-grid-column dataField="BirthDate">
<dxi-data-grid-validation-rule type="required"></dxi-data-grid-validation-rule>
</dxi-data-grid-column>
<dxi-data-grid-column dataField="HireDate">
<dxi-data-grid-validation-rule type="required"></dxi-data-grid-validation-rule>
</dxi-data-grid-column>
<dxi-data-grid-column dataField="Country">
<dxi-data-grid-validation-rule type="required"></dxi-data-grid-validation-rule>
</dxi-data-grid-column>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid>
<DxEditing
mode="popup"
:allow-updating="true"
:allow-adding="true"
:allow-deleting="true"
/>
<DxColumn data-field="FullName">
<DxRequiredRule />
</DxColumn>
<DxColumn data-field="Position">
<DxRequiredRule />
</DxColumn>
<DxColumn data-field="BirthDate">
<DxRequiredRule />
</DxColumn>
<DxColumn data-field="HireDate">
<DxRequiredRule />
</DxColumn>
<DxColumn data-field="Country">
<DxRequiredRule />
</DxColumn>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxEditing, DxColumn, DxRequiredRule } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, Editing, Column, RequiredRule } from 'devextreme-react/data-grid';
function App() {
return (
<DataGrid>
<Editing
mode="popup"
allowUpdating={true}
allowDeleting={true}
allowAdding={true}
/>
<Column dataField="FullName">
<RequiredRule />
</Column>
<Column dataField="Position">
<RequiredRule />
</Column>
<Column dataField="BirthDate">
<RequiredRule />
</Column>
<Column dataField="HireDate">
<RequiredRule />
</Column>
<Column dataField="Country">
<RequiredRule />
</Column>
{/* ... */}
</DataGrid>
);
}To implement validation for unchanged cells using a custom toolbar button, refer to the following example:
Select Records
Read Tutorial: DataGrid - Selection
DataGrid supports single- and multiple-row selection. To enable row selection, configure the selection.mode property.
Handle onSelectionChanged to obtain selected records at runtime. This tutorial uses onSelectionChanged to display selected employee names in an element outside the component:
jQuery
$("#dataGrid").dxDataGrid({
selection: { mode: "single" },
onSelectionChanged: function(e) {
e.component.byKey(e.currentSelectedRowKeys[0]).done(employee => {
if(employee) {
$("#selected-employee").text(`Selected employee: ${employee.FullName}`);
}
});
},
// ...
});
<html>
<!-- ... -->
<body class="dx-viewport">
<div id="app-container">
<div id="dataGrid"></div>
<p id="selected-employee"></p>
</div>
</body>
</html>ASP.NET Core Controls
<div id="app-container">
@(Html.DevExtreme().DataGrid<Employee>()
.Selection(s => s.Mode(SelectionMode.Single))
.OnSelectionChanged("handleSelectionChanged")
@* ... *@
)
<p id="selected-employee"></p>
</div>
<script>
function handleSelectionChanged(e) {
e.component.byKey(e.currentSelectedRowKeys[0]).done((employee) => {
if (employee) {
$('#selected-employee').text(`Selected employee: ${employee.FullName}`);
}
});
}
</script>Angular
<div id="app-container">
<dx-data-grid (onSelectionChanged)="selectEmployee($event)">
<dxo-data-grid-selection mode="single"></dxo-data-grid-selection>
<!-- ... -->
</dx-data-grid>
@if (selectedEmployee) {
<p id="selected-employee">
Selected employee: {{ selectedEmployee.FullName }}
</p>
}
</div>
import { Component } from '@angular/core';
import { DxDataGridTypes } from 'devextreme-angular/ui/data-grid';
import { Employee, EmployeesService } from './employees.service';
// ...
export class AppComponent {
selectedEmployee: Employee;
constructor(service: EmployeesService) {
this.selectEmployee = this.selectEmployee.bind(this);
}
selectEmployee(e: DxDataGridTypes.SelectionChangedEvent) {
e.component.byKey(e.currentSelectedRowKeys[0]).done(employee => {
if(employee) {
this.selectedEmployee = employee;
}
});
}
}Vue
<template>
<div id="app-container">
<DxDataGrid @selection-changed="selectEmployee">
<DxSelection mode="single" />
<!-- ... -->
</DxDataGrid>
<p id="selected-employee" v-if="selectedEmployee">
Selected employee: {{ selectedEmployee.FullName }}
</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { DxDataGrid, DxSelection, type DataGridTypes } from 'devextreme-vue/data-grid';
import { type Employee } from '../employees.service';
const selectedEmployee = ref<Employee | undefined>();
function selectEmployee(e: DataGridTypes.SelectionChangedEvent): void {
e.component.byKey(e.currentSelectedRowKeys[0]).done((employee: Employee) => {
if (employee) {
selectedEmployee.value = employee;
}
});
}
</script>React
import React, { useCallback, useState } from 'react';
import { DataGrid, Selection, type DataGridTypes } from 'devextreme-react/data-grid';
import { type Employee } from './employees';
function SelectedEmployee(props) {
if(props.employee) {
return (
<p id="selected-employee">
Selected employee: {props.employee.FullName}
</p>
);
}
return null;
}
function App() {
const [selectedEmployee, setSelectedEmployee] = useState();
const selectEmployee = useCallback((e: DataGridTypes.SelectionChangedEvent): void => {
e.component.byKey(e.currentSelectedRowKeys[0]).then((employee: Employee) => {
setSelectedEmployee(employee);
}).catch(() => {});
}, []);
return (
<div className="App">
<DataGrid onSelectionChanged={selectEmployee}>
<Selection mode="single" />
{/* ... */}
</DataGrid>
<SelectedEmployee employee={selectedEmployee} />
</div>
);
}Display Summaries
Read Tutorial: DataGrid - Total Summary Read Tutorial: DataGrid - Group Summary
DataGrid supports two types of data summaries:
- Total summaries: Calculated against all grid records. Configured in the totalItems array.
- Group summaries: Calculated for each data group. Configured in the groupItems array.
Each summary item applies an aggregate function specified in summaryType to display summarized values. You can use predefined aggregate functions (such as "sum", "avg", and "count") or define a custom aggregate function. This tutorial displays a "count" group summary:
jQuery
$("#dataGrid").dxDataGrid({
summary: {
groupItems: [{
summaryType: "count"
}]
},
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.Summary(s => s
.GroupItems(groupItems => {
groupItems.Add().SummaryType(SummaryType.Count);
})
)
@* ... *@
)Angular
<dx-data-grid>
<dxo-data-grid-summary>
<dxi-data-grid-group-item
summaryType="count">
</dxi-data-grid-group-item>
</dxo-data-grid-summary>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid>
<DxSummary>
<DxGroupItem summary-type="count" />
</DxSummary>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxSummary, DxGroupItem } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, Summary, GroupItem } from 'devextreme-react/data-grid';
function App() {
return (
<div className="App">
<DataGrid>
<Summary>
<GroupItem summaryType="count" />
</Summary>
{/* ... */}
</DataGrid>
</div>
);
}Customize the Toolbar
The DataGrid includes an integrated toolbar that displays predefined and custom controls. To add or remove toolbar items, declare the toolbar.items[] array. Toolbar items within the UI preserve the order in which they are declared.
This tutorial illustrates how to add the following items to the toolbar:
Predefined controls
Declare a toolbar item element and specify the name and properties that you want to customize (see the "addRowButton" configuration in the code below). If a control does not need customization, include its name only. Ensure that items[] contain controls for all features that you enabled in your DataGrid.DevExtreme components
Configure a DevExtreme component within a toolbar item element. In this tutorial, we extended the toolbar's item collection with a custom Button that expands or collapses all grid records.
jQuery
const dataGrid = $("#dataGrid").dxDataGrid({
toolbar: {
items: [
"groupPanel", {
location: "after",
widget: "dxButton",
options: {
text: "Collapse All",
width: 136,
onClick(e) {
const expanding = e.component.option("text") === "Expand All";
dataGrid.option("grouping.autoExpandAll", expanding);
e.component.option("text", expanding ? "Collapse All" : "Expand All");
},
},
}, {
name: "addRowButton",
showText: "always"
}, "exportButton", "columnChooserButton", "searchPanel",
]
},
// ...
}).dxDataGrid("instance");ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.ID("grid-container")
.Toolbar(t => t.Items(items => {
items.Add().Name(DataGridToolbarItem.GroupPanel);
items.Add()
.Location(ToolbarItemLocation.After)
.Widget(w => w.Button()
.Text("Collapse All")
.Width(136)
.OnClick("handleCollapseAllButtonClick")
);
items.Add().Name(DataGridToolbarItem.AddRowButton).ShowText(ToolbarItemShowTextMode.Always);
items.Add().Name(DataGridToolbarItem.ExportButton);
items.Add().Name(DataGridToolbarItem.ColumnChooserButton);
items.Add().Name(DataGridToolbarItem.SearchPanel);
}))
@* ... *@
)
<script>
function handleCollapseAllButtonClick(e) {
const expanding = e.component.option('text') === 'Expand All';
$('#grid-container').dxDataGrid('instance').option('grouping.autoExpandAll', expanding);
e.component.option('text', expanding ? 'Collapse All' : 'Expand All');
}
</script>Angular
<dx-data-grid ... >
<dxo-data-grid-grouping [autoExpandAll]="expanded"></dxo-data-grid-grouping>
<dxo-data-grid-toolbar>
<dxi-data-grid-item name="groupPanel"></dxi-data-grid-item>
<dxi-data-grid-item location="after">
<dx-button
[text]="expanded ? 'Collapse All' : 'Expand All'"
[width]="136"
(onClick)="expanded = !expanded">
</dx-button>
</dxi-data-grid-item>
<dxi-data-grid-item name="addRowButton" showText="always"></dxi-data-grid-item>
<dxi-data-grid-item name="exportButton"></dxi-data-grid-item>
<dxi-data-grid-item name="columnChooserButton"></dxi-data-grid-item>
<dxi-data-grid-item name="searchPanel"></dxi-data-grid-item>
</dxo-data-grid-toolbar>
<!-- ... -->
</dx-data-grid>
// ...
export class AppComponent {
// ...
expanded: boolean = true;
}
import {
// ...
DxButtonModule
} from 'devextreme-angular';
@NgModule({
// ...
imports: [
// ...
DxButtonModule
],
})
export class AppModule { }Vue
<template>
<DxDataGrid ... >
<DxGrouping :auto-expand-all="expanded" />
<DxToolbar>
<DxItem name="groupPanel" />
<DxItem location="after" template="button-template" />
<DxItem name="addRowButton" show-text="always" />
<DxItem name="exportButton" />
<DxItem name="columnChooserButton" />
<DxItem name="searchPanel" />
</DxToolbar>
<template #button-template>
<DxButton
:text="expanded ? 'Collapse All' : 'Expand All'"
:width="136"
@click="expanded = !expanded"
/>
</template>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { DxDataGrid, DxGrouping, DxToolbar, DxItem } from 'devextreme-vue/data-grid';
import { DxButton } from 'devextreme-vue/button';
const expanded = ref<boolean>(true);
</script>React
import { DataGrid, Grouping, Toolbar, Item } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
function App() {
const [expanded, setExpanded] = useState(true);
return (
<DataGrid>
<Grouping autoExpandAll={expanded} />
<Toolbar>
<Item name="groupPanel" />
<Item location="after">
<Button
text={expanded ? 'Collapse All' : 'Expand All'}
width={136}
onClick={() => setExpanded(prevExpanded => !prevExpanded)}
/>
</Item>
<Item name="addRowButton" showText="always" />
<Item name="exportButton" />
<Item name="columnChooserButton" />
<Item name="searchPanel" />
</Toolbar>
{/* ... */}
</DataGrid>
);
}Configure Master-Detail Interface
Read Tutorial: DataGrid - Master-Detail Interface
DataGrid supports master-detail data presentation. You can display detail data in expandable sections below master rows. To configure master-detail mode, set masterDetail.enabled to true and specify a template. This tutorial configures a template that displays employee images from file paths stored in the component data source:
jQuery
$("#dataGrid").dxDataGrid({
masterDetail: {
enabled: true,
template: function (_, options) {
const employee = options.data;
const photo = $("<img>")
.addClass("employee-photo")
.attr("src", employee.Photo);
const notes = $("<p>")
.addClass("employee-notes")
.text(employee.Notes);
return $("<div>").append(photo, notes);
}
},
// ...
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.MasterDetail(m => m
.Enabled(true)
.Template(new JS ("masterDetailTemplate"))
)
@* ... *@
)
<script>
function masterDetailTemplate(_, options) {
const employee = options.data;
const photo = $('<img>').addClass('employee-photo').attr('src', employee.Photo);
const notes = $('<p>').addClass('employee-notes').text(employee.Notes);
return $('<div>').append(photo, notes);
}
</script>Angular
<dx-data-grid>
<dxo-data-grid-master-detail
[enabled]="true"
[template]="'employee-info'">
</dxo-data-grid-master-detail>
<div *dxTemplate="let employee of 'employee-info'">
<img class="employee-photo" [src]="employee.data.Photo">
<p class="employee-notes">{{ employee.data.Notes }}</p>
</div>
<!-- ... -->
</dx-data-grid>Vue
<template>
<DxDataGrid>
<DxMasterDetail
:enabled="true"
template="employee-info"
/>
<template #employee-info="{ data: employee }">
<div>
<img class="employee-photo" :src="employee.data.Photo">
<p class="employee-notes">{{ employee.data.Notes }}</p>
</div>
</template>
<!-- ... -->
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxMasterDetail } from 'devextreme-vue/data-grid';
</script>React
import { DataGrid, MasterDetail } from 'devextreme-react/data-grid';
function DetailSection(props) {
const employee = props.data.data;
return (
<div>
<img
className="employee-photo"
alt={employee.FullName}
src={employee.Photo}
/>
<p className="employee-notes">{employee.Notes}</p>
</div>
);
}
function App() {
return (
<DataGrid>
<MasterDetail
enabled={true}
component={DetailSection}
/>
{/* ... */}
</DataGrid>
);
}Export Data
DataGrid supports exporting data to Excel and PDF. Export functionality uses the following third-party libraries:
Excel: DevExtreme ExcelJS v4.4.1+ and FileSaver v2.0.2+
PDF: jsPDF v2.3.1+
To allow users to export data, set export.enabled to true and define an onExporting event handler. The component executes this handler when users click a button in the "exportButton" toolbar item. Call excelExporter.exportDataGrid(options) or pdfExporter.exportDataGrid(options) in this handler as follows:
jQuery
<html>
<head>
<!-- ... -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.0/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/devextreme-exceljs-fork@4.4.1/dist/dx-exceljs-fork.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.2/FileSaver.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.3.1/jspdf.umd.min.js"></script>
<!-- DevExtreme scripts are referenced here -->
<!-- ... -->
</head>
</html>
// This code is used for backwards compatibility with the older jsPDF variable name
// Read more: https://github.com/MrRio/jsPDF/releases/tag/v2.0.0
// window.jsPDF = window.jspdf.jsPDF;
$(function() {
$("#dataGrid").dxDataGrid({
export: {
enabled: true,
formats: ['xlsx', 'pdf']
},
onExporting(e) {
if (e.format === 'xlsx') {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Main sheet');
DevExpress.excelExporter.exportDataGrid({
worksheet,
component: e.component,
}).then(() => {
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
});
});
} else if (e.format === 'pdf') {
const doc = new window.jspdf.jsPDF();
DevExpress.pdfExporter.exportDataGrid({
jsPDFDocument: doc,
component: e.component,
}).then(() => {
doc.save('DataGrid.pdf');
});
}
}
});
});ASP.NET Core Controls
@(Html.DevExtreme().DataGrid<Employee>()
.Export(e => e
.Enabled(true)
.Formats(new[] { DataGridExportFormat.Pdf, DataGridExportFormat.Xlsx })
)
.OnExporting("handleDataGridExporting")
@* ... *@
)
<script>
function handleDataGridExporting(e) {
if (e.format === 'xlsx') {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Main sheet');
DevExpress.excelExporter.exportDataGrid({
worksheet,
component: e.component,
}).then(() => {
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
});
});
} else if (e.format === 'pdf') {
const doc = new window.jspdf.jsPDF();
DevExpress.pdfExporter.exportDataGrid({
jsPDFDocument: doc,
component: e.component,
}).then(() => {
doc.save('DataGrid.pdf');
});
}
}
</script>Angular
npm install --save devextreme-exceljs-fork file-saver npm install jspdf
<dx-data-grid (onExporting)="exportGrid($event)">
<dxo-data-grid-export
[enabled]="true"
[formats]="['xlsx', 'pdf']"
></dxo-data-grid-export>
<!-- ... -->
</dx-data-grid>
import { type DxDataGridTypes } from 'devextreme-angular/ui/data-grid';
import { Workbook } from 'devextreme-exceljs-fork';
import saveAs from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';
import { exportDataGrid as exportDataGridToPdf } from 'devextreme/pdf_exporter';
import { jsPDF } from 'jspdf';
// ...
export class AppComponent {
exportGrid(e: DxDataGridTypes.ExportingEvent) {
if (e.format === 'xlsx') {
const workbook = new Workbook();
const worksheet = workbook.addWorksheet("Main sheet");
exportDataGrid({
worksheet: worksheet,
component: e.component,
}).then(function() {
workbook.xlsx.writeBuffer().then(function(buffer) {
saveAs(new Blob([buffer], { type: "application/octet-stream" }), "DataGrid.xlsx");
});
});
} else if (e.format === 'pdf') {
const doc = new jsPDF();
exportDataGridToPdf({
jsPDFDocument: doc,
component: e.component,
}).then(() => {
doc.save('DataGrid.pdf');
});
}
}
}Vue
npm install --save devextreme-exceljs-fork file-saver npm install jspdf
<template>
<DxDataGrid @exporting="exportGrid">
<!-- ... -->
<DxExport
:enabled="true"
:formats="['xlsx', 'pdf']"
/>
</DxDataGrid>
</template>
<script setup lang="ts">
import { DxDataGrid, DxExport, type DxDataGridTypes } from 'devextreme-vue/data-grid';
import { Workbook } from 'devextreme-exceljs-fork';
import { saveAs } from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';
import { jsPDF } from 'jspdf';
import { exportDataGrid as exportDataGridToPdf} from 'devextreme/pdf_exporter';
function exportGrid(e: DxDataGridTypes.ExportingEvent): void {
if (e.format === 'xlsx') {
const workbook = new Workbook();
const worksheet = workbook.addWorksheet('Main sheet');
exportDataGrid({
worksheet: worksheet,
component: e.component,
}).then(() => {
workbook.xlsx.writeBuffer().then((buffer: ArrayBuffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
});
});
} else if (e.format === 'pdf') {
const doc = new jsPDF();
exportDataGridToPdf({
jsPDFDocument: doc,
component: e.component,
}).then(() => {
doc.save('DataGrid.pdf');
});
}
}
</script>React
npm install --save devextreme-exceljs-fork file-saver npm install jspdf
import React, { useState } from 'react';
import { DataGrid, Export, type DataGridTypes } from 'devextreme-react/data-grid';
import { Workbook } from 'devextreme-exceljs-fork';
import saveAs from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';
import { jsPDF } from 'jspdf';
import { exportDataGrid as exportDataGridToPdf} from 'devextreme/pdf_exporter';
// ...
const exportFormats = ['xlsx', 'pdf'];
function exportGrid(e: DataGridTypes.ExportingEvent) {
if (e.format === 'xlsx') {
const workbook = new Workbook();
const worksheet = workbook.addWorksheet("Main sheet");
exportDataGrid({
worksheet: worksheet,
component: e.component,
}).then(function() {
workbook.xlsx.writeBuffer().then(function(buffer) {
saveAs(new Blob([buffer], { type: "application/octet-stream" }), "DataGrid.xlsx");
});
});
} else if (e.format === 'pdf') {
const doc = new jsPDF();
exportDataGridToPdf({
jsPDFDocument: doc,
component: e.component,
}).then(() => {
doc.save('DataGrid.pdf');
});
}
}
function App() {
return (
<DataGrid onExporting={exportGrid}>
<Export enabled={true} formats={exportFormats} />
{/* ... */}
</DataGrid>
);
}Export to Excel Overview Demo Export to PDF Overview Demo
For more information about the DevExtreme DataGrid, refer to the following resources: