All docs
V20.1
20.2
20.1
19.2
The page you are viewing does not exist in version 19.2. This link will take you to the root page.
19.1
The page you are viewing does not exist in version 19.1. This link will take you to the root page.
18.2
The page you are viewing does not exist in version 18.2. This link will take you to the root page.
18.1
The page you are viewing does not exist in version 18.1. This link will take you to the root page.
17.2
The page you are viewing does not exist in version 17.2. This link will take you to the root page.
17.1
The page you are viewing does not exist in version 17.1. This link will take you to the root page.
16.2
The page you are viewing does not exist in version 16.2. This link will take you to the root page.
A newer version of this page is available. Switch to the current version.

Getting Started with DataGrid

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.

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 widget that looks as follows:

Refer to the following sections for details on each configuration step. You can also find the full code in the following GitHub repository: getting-started-with-datagrid

Create a DataGrid

jQuery

Add DevExtreme to your jQuery application and use the following code to create a DataGrid:

index.js
index.html
index.css
$(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/20.1.9/css/dx.common.css">
        <link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/20.1.9/css/dx.light.css">
        <link rel="stylesheet" href="index.css">

        <script type="text/javascript" src="https://cdn3.devexpress.com/jslib/20.1.9/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;
}
Angular

Add DevExtreme to your Angular application and use the following code to create a DataGrid:

app.component.html
app.component.ts
app.module.ts
app.component.css
<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

Add DevExtreme to your Vue application and use the following code to create a DataGrid:

App.vue
<template>
    <div id="app-container">
        <DxDataGrid id="dataGrid">
            <!-- Configuration goes here -->
        </DxDataGrid>
    </div>
</template>

<script>
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import { DxDataGrid } from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid
    }
}
</script>

<style>
#dataGrid {
    height: 500px;
}
</style>
React

Add DevExtreme to your React application and use the following code to create a DataGrid:

App.js
App.css
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.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

The DataGrid component can load and update data from different data source types. To use a local array, assign it to the dataSource option and specify the key field in the keyExpr option. If you want to use another data source type, refer to one of the following articles:

jQuery
index.js
data.js
$(function() {
    $("#dataGrid").dxDataGrid({
        dataSource: employees,
        keyExpr: "EmployeeID",
    });
});
const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
}, {
    "EmployeeID": 2,
    "FullName": "Andrew Fuller",
    "Position": "Vice President, Sales",
    "TitleOfCourtesy": "Dr.",
    "BirthDate": "1972-02-19T00:00:00.000Z",
    "HireDate": "2011-08-14T00:00:00.000Z",
    "Address": "908 W. Capital Way",
    "City": "Tacoma",
    "Region": "WA",
    "PostalCode": "98401",
    "Country": "USA",
    "HomePhone": "(206) 555-9482",
    "Extension": "3457",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/02.png",
    "Notes": "Andrew received his BTS commercial in 1994 and a Ph.D. in international marketing from the University of Dallas in 2001.  He is fluent in French and Italian and reads German.  He joined the company as a sales representative, was promoted to sales manager in January 2012 and to vice president of sales in March 2013.  Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.",
    "ReportsTo": null
}, {
    "EmployeeID": 3,
    "FullName": "Janet Leverling",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1983-08-30T00:00:00.000Z",
    "HireDate": "2011-04-01T00:00:00.000Z",
    "Address": "722 Moss Bay Blvd.",
    "City": "Kirkland",
    "Region": "WA",
    "PostalCode": "98033",
    "Country": "USA",
    "HomePhone": "(206) 555-3412",
    "Extension": "3355",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/09.png",
    "Notes": "Janet has a BS degree in chemistry from Boston College (2004).  She has also completed a certificate program in food retailing management.  Janet was hired as a sales associate in 2011 and promoted to sales representative in February 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 4,
    "FullName": "Margaret Peacock",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mrs.",
    "BirthDate": "1957-09-19T00:00:00.000Z",
    "HireDate": "2012-05-03T00:00:00.000Z",
    "Address": "4110 Old Redmond Rd.",
    "City": "Redmond",
    "Region": "WA",
    "PostalCode": "98052",
    "Country": "USA",
    "HomePhone": "(206) 555-8122",
    "Extension": "5176",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/04.png",
    "Notes": "Margaret holds a BA in English literature from Concordia College (1978) and an MA from the American Institute of Culinary Arts (1986).  She was assigned to the London office temporarily from July through November 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 5,
    "FullName": "Steven Buchanan",
    "Position": "Sales Manager",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1975-03-04T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "14 Garrett Hill",
    "City": "London",
    "Region": "UK",
    "PostalCode": "SW1 8JR",
    "Country": "UK",
    "HomePhone": "(71) 555-4848",
    "Extension": "3453",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/05.png",
    "Notes": "Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree in 1996.  Upon joining the company as a sales representative in 2012, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London.  He was promoted to sales manager in March 2013.  Mr. Buchanan has completed the courses \"Successful Telemarketing\" and \"International Sales Management.\"  He is fluent in French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 6,
    "FullName": "Michael Suyama",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1983-07-02T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "Coventry House\r\nMiner Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "EC2 7JR",
    "Country": "UK",
    "HomePhone": "(71) 555-7773",
    "Extension": "428",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/01.png",
    "Notes": "Michael is a graduate of Sussex University (MA, economics, 2003) and the University of California at Los Angeles (MBA, marketing, 2006). He has also taken the courses \"Multi-Cultural Selling\" and \"Time Management for the Sales Professional.\"  He is fluent in Japanese and can read and write French, Portuguese, and Spanish.",
    "ReportsTo": 5
}, {
    "EmployeeID": 7,
    "FullName": "Robert King",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1980-05-29T00:00:00.000Z",
    "HireDate": "2012-01-02T00:00:00.000Z",
    "Address": "Edgeham Hollow\r\nWinchester Way",
    "City": "London",
    "Region": "UK",
    "PostalCode": "RG1 9SP",
    "Country": "UK",
    "HomePhone": "(71) 555-5598",
    "Extension": "465",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/07.png",
    "Notes": "Robert King served in the Peace Corps and traveled extensively before completing his degree in English at the University of Michigan in 2002, the year he joined the company.  After completing a course entitled \"Selling in Europe,\" he was transferred to the London office in March 2013.",
    "ReportsTo": 5
}, {
    "EmployeeID": 8,
    "FullName": "Laura Callahan",
    "Position": "Inside Sales Coordinator",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1978-01-09T00:00:00.000Z",
    "HireDate": "2012-03-05T00:00:00.000Z",
    "Address": "4726 - 11th Ave. N.E.",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98105",
    "Country": "USA",
    "HomePhone": "(206) 555-1189",
    "Extension": "2344",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/08.png",
    "Notes": "Laura received a BA in psychology from the University of Washington.  She has also completed a course in business French.  She reads and writes French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 9,
    "FullName": "Brett Wade",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1986-01-27T00:00:00.000Z",
    "HireDate": "2012-11-15T00:00:00.000Z",
    "Address": "7 Houndstooth Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "WG2 7LT",
    "Country": "UK",
    "HomePhone": "(71) 555-4444",
    "Extension": "452",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/03.png",
    "Notes": "Brett has a BA degree in English from St. Lawrence College.  He is fluent in French and German.",
    "ReportsTo": 5
}];
Angular
app.component.html
app.component.ts
employees.service.ts
<dx-data-grid
    [dataSource]="employees"
    keyExpr="EmployeeID">
</dx-data-grid>
import { Component } from '@angular/core';
import { Employee, EmployeesService } from './employees.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
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
}

const employees: Employee[] = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
}, {
    "EmployeeID": 2,
    "FullName": "Andrew Fuller",
    "Position": "Vice President, Sales",
    "TitleOfCourtesy": "Dr.",
    "BirthDate": "1972-02-19T00:00:00.000Z",
    "HireDate": "2011-08-14T00:00:00.000Z",
    "Address": "908 W. Capital Way",
    "City": "Tacoma",
    "Region": "WA",
    "PostalCode": "98401",
    "Country": "USA",
    "HomePhone": "(206) 555-9482",
    "Extension": "3457",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/02.png",
    "Notes": "Andrew received his BTS commercial in 1994 and a Ph.D. in international marketing from the University of Dallas in 2001.  He is fluent in French and Italian and reads German.  He joined the company as a sales representative, was promoted to sales manager in January 2012 and to vice president of sales in March 2013.  Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.",
    "ReportsTo": null
}, {
    "EmployeeID": 3,
    "FullName": "Janet Leverling",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1983-08-30T00:00:00.000Z",
    "HireDate": "2011-04-01T00:00:00.000Z",
    "Address": "722 Moss Bay Blvd.",
    "City": "Kirkland",
    "Region": "WA",
    "PostalCode": "98033",
    "Country": "USA",
    "HomePhone": "(206) 555-3412",
    "Extension": "3355",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/09.png",
    "Notes": "Janet has a BS degree in chemistry from Boston College (2004).  She has also completed a certificate program in food retailing management.  Janet was hired as a sales associate in 2011 and promoted to sales representative in February 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 4,
    "FullName": "Margaret Peacock",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mrs.",
    "BirthDate": "1957-09-19T00:00:00.000Z",
    "HireDate": "2012-05-03T00:00:00.000Z",
    "Address": "4110 Old Redmond Rd.",
    "City": "Redmond",
    "Region": "WA",
    "PostalCode": "98052",
    "Country": "USA",
    "HomePhone": "(206) 555-8122",
    "Extension": "5176",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/04.png",
    "Notes": "Margaret holds a BA in English literature from Concordia College (1978) and an MA from the American Institute of Culinary Arts (1986).  She was assigned to the London office temporarily from July through November 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 5,
    "FullName": "Steven Buchanan",
    "Position": "Sales Manager",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1975-03-04T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "14 Garrett Hill",
    "City": "London",
    "Region": "UK",
    "PostalCode": "SW1 8JR",
    "Country": "UK",
    "HomePhone": "(71) 555-4848",
    "Extension": "3453",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/05.png",
    "Notes": "Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree in 1996.  Upon joining the company as a sales representative in 2012, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London.  He was promoted to sales manager in March 2013.  Mr. Buchanan has completed the courses \"Successful Telemarketing\" and \"International Sales Management.\"  He is fluent in French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 6,
    "FullName": "Michael Suyama",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1983-07-02T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "Coventry House\r\nMiner Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "EC2 7JR",
    "Country": "UK",
    "HomePhone": "(71) 555-7773",
    "Extension": "428",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/01.png",
    "Notes": "Michael is a graduate of Sussex University (MA, economics, 2003) and the University of California at Los Angeles (MBA, marketing, 2006). He has also taken the courses \"Multi-Cultural Selling\" and \"Time Management for the Sales Professional.\"  He is fluent in Japanese and can read and write French, Portuguese, and Spanish.",
    "ReportsTo": 5
}, {
    "EmployeeID": 7,
    "FullName": "Robert King",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1980-05-29T00:00:00.000Z",
    "HireDate": "2012-01-02T00:00:00.000Z",
    "Address": "Edgeham Hollow\r\nWinchester Way",
    "City": "London",
    "Region": "UK",
    "PostalCode": "RG1 9SP",
    "Country": "UK",
    "HomePhone": "(71) 555-5598",
    "Extension": "465",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/07.png",
    "Notes": "Robert King served in the Peace Corps and traveled extensively before completing his degree in English at the University of Michigan in 2002, the year he joined the company.  After completing a course entitled \"Selling in Europe,\" he was transferred to the London office in March 2013.",
    "ReportsTo": 5
}, {
    "EmployeeID": 8,
    "FullName": "Laura Callahan",
    "Position": "Inside Sales Coordinator",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1978-01-09T00:00:00.000Z",
    "HireDate": "2012-03-05T00:00:00.000Z",
    "Address": "4726 - 11th Ave. N.E.",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98105",
    "Country": "USA",
    "HomePhone": "(206) 555-1189",
    "Extension": "2344",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/08.png",
    "Notes": "Laura received a BA in psychology from the University of Washington.  She has also completed a course in business French.  She reads and writes French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 9,
    "FullName": "Brett Wade",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1986-01-27T00:00:00.000Z",
    "HireDate": "2012-11-15T00:00:00.000Z",
    "Address": "7 Houndstooth Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "WG2 7LT",
    "Country": "UK",
    "HomePhone": "(71) 555-4444",
    "Extension": "452",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/03.png",
    "Notes": "Brett has a BA degree in English from St. Lawrence College.  He is fluent in French and German.",
    "ReportsTo": 5
}];

@Injectable({
    providedIn: 'root'
})
export class EmployeesService {
    getEmployees(): Employee[] {
        return employees;
    }
}
Vue
App.vue
employees.service.js
<template>
    <div id="app-container">
        <DxDataGrid
            :data-source="employees"
            key-expr="EmployeeID">
        </DxDataGrid>
    </div>
</template>

<script>
// ...
import service from './employees.service';

export default {
    // ...
    data() {
        return {
            employees: service.getEmployees(),
        }
    },
}
</script>
const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
}, {
    "EmployeeID": 2,
    "FullName": "Andrew Fuller",
    "Position": "Vice President, Sales",
    "TitleOfCourtesy": "Dr.",
    "BirthDate": "1972-02-19T00:00:00.000Z",
    "HireDate": "2011-08-14T00:00:00.000Z",
    "Address": "908 W. Capital Way",
    "City": "Tacoma",
    "Region": "WA",
    "PostalCode": "98401",
    "Country": "USA",
    "HomePhone": "(206) 555-9482",
    "Extension": "3457",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/02.png",
    "Notes": "Andrew received his BTS commercial in 1994 and a Ph.D. in international marketing from the University of Dallas in 2001.  He is fluent in French and Italian and reads German.  He joined the company as a sales representative, was promoted to sales manager in January 2012 and to vice president of sales in March 2013.  Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.",
    "ReportsTo": null
}, {
    "EmployeeID": 3,
    "FullName": "Janet Leverling",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1983-08-30T00:00:00.000Z",
    "HireDate": "2011-04-01T00:00:00.000Z",
    "Address": "722 Moss Bay Blvd.",
    "City": "Kirkland",
    "Region": "WA",
    "PostalCode": "98033",
    "Country": "USA",
    "HomePhone": "(206) 555-3412",
    "Extension": "3355",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/09.png",
    "Notes": "Janet has a BS degree in chemistry from Boston College (2004).  She has also completed a certificate program in food retailing management.  Janet was hired as a sales associate in 2011 and promoted to sales representative in February 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 4,
    "FullName": "Margaret Peacock",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mrs.",
    "BirthDate": "1957-09-19T00:00:00.000Z",
    "HireDate": "2012-05-03T00:00:00.000Z",
    "Address": "4110 Old Redmond Rd.",
    "City": "Redmond",
    "Region": "WA",
    "PostalCode": "98052",
    "Country": "USA",
    "HomePhone": "(206) 555-8122",
    "Extension": "5176",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/04.png",
    "Notes": "Margaret holds a BA in English literature from Concordia College (1978) and an MA from the American Institute of Culinary Arts (1986).  She was assigned to the London office temporarily from July through November 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 5,
    "FullName": "Steven Buchanan",
    "Position": "Sales Manager",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1975-03-04T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "14 Garrett Hill",
    "City": "London",
    "Region": "UK",
    "PostalCode": "SW1 8JR",
    "Country": "UK",
    "HomePhone": "(71) 555-4848",
    "Extension": "3453",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/05.png",
    "Notes": "Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree in 1996.  Upon joining the company as a sales representative in 2012, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London.  He was promoted to sales manager in March 2013.  Mr. Buchanan has completed the courses \"Successful Telemarketing\" and \"International Sales Management.\"  He is fluent in French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 6,
    "FullName": "Michael Suyama",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1983-07-02T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "Coventry House\r\nMiner Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "EC2 7JR",
    "Country": "UK",
    "HomePhone": "(71) 555-7773",
    "Extension": "428",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/01.png",
    "Notes": "Michael is a graduate of Sussex University (MA, economics, 2003) and the University of California at Los Angeles (MBA, marketing, 2006). He has also taken the courses \"Multi-Cultural Selling\" and \"Time Management for the Sales Professional.\"  He is fluent in Japanese and can read and write French, Portuguese, and Spanish.",
    "ReportsTo": 5
}, {
    "EmployeeID": 7,
    "FullName": "Robert King",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1980-05-29T00:00:00.000Z",
    "HireDate": "2012-01-02T00:00:00.000Z",
    "Address": "Edgeham Hollow\r\nWinchester Way",
    "City": "London",
    "Region": "UK",
    "PostalCode": "RG1 9SP",
    "Country": "UK",
    "HomePhone": "(71) 555-5598",
    "Extension": "465",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/07.png",
    "Notes": "Robert King served in the Peace Corps and traveled extensively before completing his degree in English at the University of Michigan in 2002, the year he joined the company.  After completing a course entitled \"Selling in Europe,\" he was transferred to the London office in March 2013.",
    "ReportsTo": 5
}, {
    "EmployeeID": 8,
    "FullName": "Laura Callahan",
    "Position": "Inside Sales Coordinator",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1978-01-09T00:00:00.000Z",
    "HireDate": "2012-03-05T00:00:00.000Z",
    "Address": "4726 - 11th Ave. N.E.",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98105",
    "Country": "USA",
    "HomePhone": "(206) 555-1189",
    "Extension": "2344",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/08.png",
    "Notes": "Laura received a BA in psychology from the University of Washington.  She has also completed a course in business French.  She reads and writes French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 9,
    "FullName": "Brett Wade",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1986-01-27T00:00:00.000Z",
    "HireDate": "2012-11-15T00:00:00.000Z",
    "Address": "7 Houndstooth Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "WG2 7LT",
    "Country": "UK",
    "HomePhone": "(71) 555-4444",
    "Extension": "452",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/03.png",
    "Notes": "Brett has a BA degree in English from St. Lawrence College.  He is fluent in French and German.",
    "ReportsTo": 5
}];

export default {
    getEmployees() {
        return employees;
    }
}
React
App.js
employees.js
import React from 'react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid
} from 'devextreme-react/data-grid';
import { employees } from './employees';

function App() {
    return (
        <div className="App">
            <DataGrid
                dataSource={employees}
                keyExpr="EmployeeID">
            </DataGrid>
        </div>
    );
}

export default App;
export const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
}, {
    "EmployeeID": 2,
    "FullName": "Andrew Fuller",
    "Position": "Vice President, Sales",
    "TitleOfCourtesy": "Dr.",
    "BirthDate": "1972-02-19T00:00:00.000Z",
    "HireDate": "2011-08-14T00:00:00.000Z",
    "Address": "908 W. Capital Way",
    "City": "Tacoma",
    "Region": "WA",
    "PostalCode": "98401",
    "Country": "USA",
    "HomePhone": "(206) 555-9482",
    "Extension": "3457",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/02.png",
    "Notes": "Andrew received his BTS commercial in 1994 and a Ph.D. in international marketing from the University of Dallas in 2001.  He is fluent in French and Italian and reads German.  He joined the company as a sales representative, was promoted to sales manager in January 2012 and to vice president of sales in March 2013.  Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.",
    "ReportsTo": null
}, {
    "EmployeeID": 3,
    "FullName": "Janet Leverling",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1983-08-30T00:00:00.000Z",
    "HireDate": "2011-04-01T00:00:00.000Z",
    "Address": "722 Moss Bay Blvd.",
    "City": "Kirkland",
    "Region": "WA",
    "PostalCode": "98033",
    "Country": "USA",
    "HomePhone": "(206) 555-3412",
    "Extension": "3355",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/09.png",
    "Notes": "Janet has a BS degree in chemistry from Boston College (2004).  She has also completed a certificate program in food retailing management.  Janet was hired as a sales associate in 2011 and promoted to sales representative in February 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 4,
    "FullName": "Margaret Peacock",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mrs.",
    "BirthDate": "1957-09-19T00:00:00.000Z",
    "HireDate": "2012-05-03T00:00:00.000Z",
    "Address": "4110 Old Redmond Rd.",
    "City": "Redmond",
    "Region": "WA",
    "PostalCode": "98052",
    "Country": "USA",
    "HomePhone": "(206) 555-8122",
    "Extension": "5176",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/04.png",
    "Notes": "Margaret holds a BA in English literature from Concordia College (1978) and an MA from the American Institute of Culinary Arts (1986).  She was assigned to the London office temporarily from July through November 2012.",
    "ReportsTo": 2
}, {
    "EmployeeID": 5,
    "FullName": "Steven Buchanan",
    "Position": "Sales Manager",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1975-03-04T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "14 Garrett Hill",
    "City": "London",
    "Region": "UK",
    "PostalCode": "SW1 8JR",
    "Country": "UK",
    "HomePhone": "(71) 555-4848",
    "Extension": "3453",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/05.png",
    "Notes": "Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree in 1996.  Upon joining the company as a sales representative in 2012, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London.  He was promoted to sales manager in March 2013.  Mr. Buchanan has completed the courses \"Successful Telemarketing\" and \"International Sales Management.\"  He is fluent in French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 6,
    "FullName": "Michael Suyama",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1983-07-02T00:00:00.000Z",
    "HireDate": "2012-10-17T00:00:00.000Z",
    "Address": "Coventry House\r\nMiner Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "EC2 7JR",
    "Country": "UK",
    "HomePhone": "(71) 555-7773",
    "Extension": "428",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/01.png",
    "Notes": "Michael is a graduate of Sussex University (MA, economics, 2003) and the University of California at Los Angeles (MBA, marketing, 2006). He has also taken the courses \"Multi-Cultural Selling\" and \"Time Management for the Sales Professional.\"  He is fluent in Japanese and can read and write French, Portuguese, and Spanish.",
    "ReportsTo": 5
}, {
    "EmployeeID": 7,
    "FullName": "Robert King",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1980-05-29T00:00:00.000Z",
    "HireDate": "2012-01-02T00:00:00.000Z",
    "Address": "Edgeham Hollow\r\nWinchester Way",
    "City": "London",
    "Region": "UK",
    "PostalCode": "RG1 9SP",
    "Country": "UK",
    "HomePhone": "(71) 555-5598",
    "Extension": "465",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/07.png",
    "Notes": "Robert King served in the Peace Corps and traveled extensively before completing his degree in English at the University of Michigan in 2002, the year he joined the company.  After completing a course entitled \"Selling in Europe,\" he was transferred to the London office in March 2013.",
    "ReportsTo": 5
}, {
    "EmployeeID": 8,
    "FullName": "Laura Callahan",
    "Position": "Inside Sales Coordinator",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1978-01-09T00:00:00.000Z",
    "HireDate": "2012-03-05T00:00:00.000Z",
    "Address": "4726 - 11th Ave. N.E.",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98105",
    "Country": "USA",
    "HomePhone": "(206) 555-1189",
    "Extension": "2344",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/08.png",
    "Notes": "Laura received a BA in psychology from the University of Washington.  She has also completed a course in business French.  She reads and writes French.",
    "ReportsTo": 2
}, {
    "EmployeeID": 9,
    "FullName": "Brett Wade",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Mr.",
    "BirthDate": "1986-01-27T00:00:00.000Z",
    "HireDate": "2012-11-15T00:00:00.000Z",
    "Address": "7 Houndstooth Rd.",
    "City": "London",
    "Region": "UK",
    "PostalCode": "WG2 7LT",
    "Country": "UK",
    "HomePhone": "(71) 555-4444",
    "Extension": "452",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/03.png",
    "Notes": "Brett has a BA degree in English from St. Lawrence College.  He is fluent in French and German.",
    "ReportsTo": 5
}];

If you run this code, a DataGrid is created with a column for each data field. All the columns have equal widths and the same order as their data fields.

Customize Columns

To customize grid columns, declare the columns array. This array can contain objects (column configurations) or text strings (data field names). You can use text strings if you do not need to specify column options except the dataField.

Reorder Columns

To reorder grid columns, change their order in the columns array. Users can also reorder columns if you enable the allowColumnReordering option.

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        columns: [{
            dataField: "FullName"
        }, {
            dataField: "Position"
        }, {
            dataField: "BirthDate", 
            dataType: "date",
        }, {
            dataField: "HireDate", 
            dataType: "date",
        },"City", {
            dataField: "Country"
        },
        "Address",
        "HomePhone",
        {
            dataField: "PostalCode",
        }],
        allowColumnReordering: true,
    });
});
Angular
app.component.html
<dx-data-grid ...
    [allowColumnReordering]="true">
    <dxi-column dataField="FullName"></dxi-column>
    <dxi-column dataField="Position"></dxi-column>
    <dxi-column
        dataField="BirthDate"
        dataType="date">
    </dxi-column>
    <dxi-column
        dataField="HireDate"
        dataType="date">
    </dxi-column>
    <dxi-column dataField="City"></dxi-column>
    <dxi-column dataField="Country"></dxi-column>
    <dxi-column dataField="Address"></dxi-column>
    <dxi-column dataField="HomePhone"></dxi-column>
    <dxi-column dataField="PostalCode"></dxi-column>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <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>
    </div>
</template>

<script>
// ...
import {
    DxDataGrid,
    DxColumn
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <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>
        </div>
    );
}

export default App;

In the code above, we also specify the "date" dataType for the BirthDate and HireDate columns because BirthDate and HireDate are stored as strings, but you want the DataGrid to treat them as date-time values.

Resize Columns

Grid columns have equal widths by default. You can set each column's width or indicate that all columns should adjust their widths to their content (columnAutoWidth). Users can resize columns if you enable the allowColumnResizing option.

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        columns: [
        // ...
        {
            dataField: "BirthDate", 
            dataType: "date",
            width: 100,
        }, {
            dataField: "HireDate", 
            dataType: "date",
            width: 100,
        },
        // ...
        ],
        allowColumnResizing: true,
        columnAutoWidth: true,
    });
});
Angular
app.component.html
<dx-data-grid ...
    [allowColumnResizing]="true"
    [columnAutoWidth]="true">
    <!-- ... -->
    <dxi-column
        dataField="BirthDate"
        dataType="date"
        [width]="100">
    </dxi-column>
    <dxi-column
        dataField="HireDate"
        dataType="date"
        [width]="100">
    </dxi-column>
    <!-- ... -->
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ...
            :allow-column-reordering="true"
            :column-auto-width="true">
            <!-- ... -->
            <DxColumn
                data-field="BirthDate"
                data-type="date"
                :width="100">
            </DxColumn>
            <DxColumn
                data-field="HireDate"
                data-type="date"
                :width="100">
            </DxColumn>
            <!-- ... -->
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ...
                columnAutoWidth={true}
                allowColumnReordering={true}>
                {/* ... */}
                <Column
                    dataField="BirthDate"
                    dataType="date"
                    width={100}>
                </Column>
                <Column
                    dataField="HireDate"
                    dataType="date"
                    width={100}>
                </Column>
                {/* ... */}
            </DataGrid>
        </div>
    );
}

export default App;

Fix Columns

When the width of all columns exceeds the widget's width, users can scroll the grid horizontally. If you set the columnFixing.enabled option to true, users can show certain columns in the view regardless of how far they scroll the grid.

You can also enable a column's fixed option in code. This fixes the column to the widget's left edge. To change the position, set the fixedPosition option.

The following code fixes the FullName column to the default position and allows users to fix and unfix columns at runtime:

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        columnFixing: { enabled: true },
        columns: [{
            dataField: "FullName", 
            fixed: true
        },
        // ...
        ],
        // ...
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <dxi-column
        dataField="FullName"
        [fixed]="true">
    </dxi-column>
    <!-- ... -->
    <dxo-column-fixing [enabled]="true"></dxo-column-fixing>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <DxColumn
                data-field="FullName"
                :fixed="true">
            </DxColumn>
            <!-- ... -->
            <DxColumnFixing :enabled="true" />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn,
    DxColumnFixing
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn,
        DxColumnFixing
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column,
    ColumnFixing
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <Column
                    dataField="FullName"
                    fixed={true}>
                </Column>
                {/* ... */}
                <ColumnFixing enabled={true} />
            </DataGrid>
        </div>
    );
}

export default App;

Hide Columns

The DataGrid displays all columns from the columns array. To hide a column, set its visible option to false. Hidden columns appear in the columnChooser. Users can restore hidden columns from it. To enable the column chooser. set the columnChooser.enabled option to true. If a column should not be visible even in the column chooser, simply do not declare it in the columns array.

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        columns: [
        // ...
        {
            dataField: "PostalCode",
            visible: false
        }],
        columnChooser: { enabled: true },
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxi-column dataField="PostalCode" [visible]="false"></dxi-column>
    <dxo-column-chooser [enabled]="true"></dxo-column-chooser>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <DxColumn data-field="PostalCode" :visible="false" />
            <DxColumnChooser :enabled="true" />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn,
    DxColumnChooser
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn,
        DxColumnChooser
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column,
    ColumnChooser
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <Column dataField="PostalCode" visible={false} />
                <ColumnChooser enabled={true} />
            </DataGrid>
        </div>
    );
}

export default App;

Sort Data

The sorting.mode option specifies whether users can sort grid records by single or multiple columns. This tutorial uses the default sorting mode - single.

You can also set a column's sortOrder and sortIndex options to specify the initial sorting settings. sortIndex applies only in multiple sorting mode.

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        columns: [{
            dataField: "Country",
            sortOrder: "asc",
        },
        // ...
        ],
        // sorting: { mode: "single" },
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxi-column
        dataField="Country"
        sortOrder="asc">
    </dxi-column>
    <!-- <dxo-sorting [mode]="single"></dxo-sorting> -->
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <DxColumn
                data-field="Country"
                sort-order="asc">
            </DxColumn>
            <!-- <DxSorting mode="single" /> -->
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn,
    // ...
    // DxSorting
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn,
        // ...
        // DxSorting
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column,
    // ...
    // Sorting
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <Column
                    dataField="Country"
                    sortOrder="asc">
                </Column>
                {/* <Sorting mode="single" /> */}
            </DataGrid>
        </div>
    );
}

export default App;

Run the code and ensure that grid records are sorted by the Country column. Click a column header to sort the records by another column.

Filter and Search Data

The DataGrid includes the following UI elements used to filter and search data:

In this tutorial, the filterRow and searchPanel are displayed:

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        filterRow: { visible: true },
        searchPanel: { visible: true },
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxo-filter-row [visible]="true"></dxo-filter-row>
    <dxo-search-panel [visible]="true"></dxo-search-panel>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <DxFilterRow :visible="true" />
            <DxSearchPanel :visible="true" />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    // ...
    DxFilterRow,
    DxSearchPanel
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        // ...
        DxFilterRow,
        DxSearchPanel
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    // ...
    FilterRow,
    SearchPanel
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <FilterRow visible={true} />
                <SearchPanel visible={true} />
            </DataGrid>
        </div>
    );
}

export default App;

Run the code and enter a value in a filter row cell or the search panel. Grid data is filtered according to this value.

Group Data

Grid records can be grouped by single or multiple columns. To group records, users should drag and drop column headers onto the groupPanel. Enable the groupPanel.visible option to display this UI element.

To group data in code, specify a column's groupIndex option. In this tutorial, the groupIndex is specified for the Country column:

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        columns: [
        // ...
        {
            dataField: "Country",
            // ...
            groupIndex: 0,
        },
        // ...
        ],
        groupPanel: { visible: true },
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxi-column
        dataField="Country"
        ...
        [groupIndex]="0">
    </dxi-column>
    <dxo-group-panel [visible]="true"></dxo-group-panel>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <DxColumn
                data-field="Country"
                ...
                :group-index="0">
            </DxColumn>
            <DxGroupPanel :visible="true" />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn,
    // ...
    DxGroupPanel
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn,
        // ...
        DxGroupPanel
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column,
    // ...
    GroupPanel
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <Column
                    dataField="Country"
                    ...
                    groupIndex={0}>
                </Column>
                <GroupPanel visible={true} />
            </DataGrid>
        </div>
    );
}

export default App;

If you run the code, records are grouped by the Country column. This column's header is on the group panel. Drag and drop column headers to and from the group panel to change the grouping.

Edit and Validate Data

Users can add new records and update or delete existing records. To allow these operations, enable the allowAdding, allowUpdating, and allowDeleting options in the editing object. Multiple edit modes are available. This tutorial uses the pop-up edit mode.

DevExtreme includes a validation engine that checks edited values before they are saved. This engine supports different validation rule types, such as Email, Compare, Range, and more. Validation rules are specified per column; one column can use multiple rules. The code below assigns the Required rule to several columns.

jQuery
index.js
$(function() {
    $("#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" }]
        },
        // ...
        ],
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxi-column dataField="FullName">
        <dxi-validation-rule type="required"></dxi-validation-rule>
    </dxi-column>
    <dxi-column dataField="Position">
        <dxi-validation-rule type="required"></dxi-validation-rule>
    </dxi-column>
    <dxi-column ...
        dataField="BirthDate">
        <dxi-validation-rule type="required"></dxi-validation-rule>
    </dxi-column>
    <dxi-column ...
        dataField="HireDate">
        <dxi-validation-rule type="required"></dxi-validation-rule>
    </dxi-column>
    <dxi-column ...
        dataField="Country">
        <dxi-validation-rule type="required"></dxi-validation-rule>
    </dxi-column>
    <dxo-editing
        mode="popup"
        [allowUpdating]="true"
        [allowDeleting]="true"
        [allowAdding]="true">
    </dxo-editing>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <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>
            <DxEditing
                mode="popup"
                :allow-updating="true"
                :allow-adding="true"
                :allow-deleting="true"
            />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    DxColumn,
    // ...
    DxRequiredRule,
    DxEditing
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn,
        // ...
        DxRequiredRule,
        DxEditing
    },
    // ...
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import {
    DataGrid,
    Column,
    // ...
    RequiredRule,
    Editing
} from 'devextreme-react/data-grid';

function App() {
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <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>
                <Editing
                    mode="popup"
                    allowUpdating={true}
                    allowDeleting={true}
                    allowAdding={true}
                />
            </DataGrid>
        </div>
    );
}

export default App;

Run the code and click the Edit button in any row. This invokes a pop-up window that contains an edit form. When you clear the Full Name text box on this form, the following validation error is shown: "First Name is required".

Select Records

The DataGrid supports single and multiple record selection modes. Use the selection.mode option to specify the mode.

You can obtain the selected record's data in the onSelectionChanged function. In the code below, this function displays the selected employee under the DataGrid:

jQuery
index.js
index.html
index.css
$(function() {
    $("#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>
/* ... */
#app-container {
    width: 900px;
    position: relative;
}

#selected-employee {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}
Angular
app.component.html
app.component.ts
app.component.css
<div id="app-container">
    <dx-data-grid ...
        (onSelectionChanged)="selectEmployee($event)">
        <!-- ... -->
        <dxo-selection mode="single"></dxo-selection>
    </dx-data-grid>
    <p id="selected-employee" *ngIf="selectedEmployee">
        Selected employee: {{ selectedEmployee.FullName }}
    </p>
</div>
import { Component } from '@angular/core';
import { Employee, EmployeesService } from './employees.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    // ...
    selectedEmployee: Employee;

    constructor(service: EmployeesService) {
        // ...
        this.selectEmployee = this.selectEmployee.bind(this);
    }

    selectEmployee(e) {
        e.component.byKey(e.currentSelectedRowKeys[0]).done(employee => {
            if(employee) {
                this.selectedEmployee = employee;
            }
        });
    }
}
/* ... */
#app-container {
    width: 900px;
    position: relative;
}

#selected-employee {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}
Vue
App.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>
import {
    DxDataGrid,
    // ...
    DxSelection
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        // ...
        DxSelection
    },
    data() {
        return {
            // ...
            selectedEmployee: undefined,
        }
    },
    methods: {
        selectEmployee(e) {
            e.component.byKey(e.currentSelectedRowKeys[0]).done(employee => {
                if(employee) {
                    this.selectedEmployee = employee;
                }
            });
        }
    }
}
</script>

<style>
/* ... */
#app-container {
    width: 900px;
    position: relative;
}

#selected-employee {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}
</style>
React
App.js
App.css
import React, { useState } from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';
import './App.css';

import {
    DataGrid,
    Column,
    // ...
    Selection
} from 'devextreme-react/data-grid';

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 = (e) => {
        e.component.byKey(e.currentSelectedRowKeys[0]).done(employee => {
            setSelectedEmployee(employee);
        });
    }

    return (
        <div className="App">
            <DataGrid ...
                onSelectionChanged={selectEmployee}>
                {/* ... */}
                <Selection mode="single" />
            </DataGrid>
            <SelectedEmployee employee={selectedEmployee} />
        </div>
    );
}

export default App;
/* ... */
.App {
    width: 900px;
    position: relative;
}

#selected-employee {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}

Display Summaries

Summaries can be divided into two groups:

  • 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 displays a value that is the result of applying an aggregate function to data. You can use predefined aggregate functions, such as "sum", "avg", and "count", or implement a custom aggregate function. To apply an aggregate function, set the summaryType option.

The code below configures a group summary that counts grid records in each group:

jQuery
index.js
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        summary: {
            groupItems: [{
                summaryType: "count"
            }]
        },
    });
});
Angular
app.component.html
<dx-data-grid ... >
    <!-- ... -->
    <dxo-summary>
        <dxi-group-item
            summaryType="count">
        </dxi-group-item>
    </dxo-summary>
</dx-data-grid>
Vue
App.vue
<template>
    <div id="app-container">
        <DxDataGrid ... >
            <!-- ... -->
            <DxSummary>
                <DxGroupItem
                    summary-type="count"
                />
            </DxSummary>
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    // ...
    DxSummary,
    DxGroupItem
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        // ...
        DxSummary,
        DxGroupItem
    },
    // ...
}
</script>
React
App.js
import React, { useState } from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';
import './App.css';

import {
    DataGrid,
    Column,
    // ...
    Summary,
    GroupItem
} from 'devextreme-react/data-grid';

// ...
function App() {
    // ...
    return (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <Summary>
                    <GroupItem
                        summaryType="count"
                    />
                </Summary>
            </DataGrid>
        </div>
    );
}

export default App;

Configure Master-Detail Interface

DataGrid allows you to display expandable detail sections under data rows. To configure a UI like this, use the masterDetail object. Set the enabled option to true and specify a template that is used as the detail section's content:

jQuery
index.js
data.js
index.css
$(function() {
    $("#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);
            }
        },
    });
});
const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
},
// ...
];
.employee-photo {
    height: 140px;
    float: left;
    padding: 0 20px 20px 0;
}

.employee-notes {
    text-align: justify;
    white-space: normal;
}

/* ... */
Angular
app.component.html
employees.service.ts
app.component.css
<dx-data-grid ... >
    <!-- ... -->
    <dxo-master-detail
        [enabled]="true"
        [template]="'employee-info'">
    </dxo-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>
// ...
const employees: Employee[] = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
},
// ...
];
// ...
.employee-photo {
    height: 140px;
    float: left;
    padding: 0 20px 20px 0;
}

.employee-notes {
    text-align: justify;
    white-space: normal;
}

/* ... */
Vue
App.vue
employees.service.js
<template>
    <div id="app-container">
        <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>
    </div>
</template>

<script>
import {
    DxDataGrid,
    // ...
    DxMasterDetail
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        // ...
        DxMasterDetail
    },
    // ...
}
</script>

<style>
.employee-photo {
    height: 140px;
    float: left;
    padding: 0 20px 20px 0;
}

.employee-notes {
    text-align: justify;
    white-space: normal;
}

/* ... */
</style>
const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
},
// ...
];
React
App.js
employees.js
App.css
import React, { useState } from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';
import './App.css';

import {
    DataGrid,
    Column,
    // ...
    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 (
        <div className="App">
            <DataGrid ... >
                {/* ... */}
                <MasterDetail
                    enabled={true}
                    component={DetailSection}
                />
            </DataGrid>
        </div>
    );
}

export default App;
export const employees = [{
    "EmployeeID": 1,
    "FullName": "Nancy Davolio",
    "Position": "Sales Representative",
    "TitleOfCourtesy": "Ms.",
    "BirthDate": "1968-12-08T00:00:00.000Z",
    "HireDate": "2011-05-01T00:00:00.000Z",
    "Address": "507 - 20th Ave. E.\r\nApt. 2A",
    "City": "Seattle",
    "Region": "WA",
    "PostalCode": "98122",
    "Country": "USA",
    "HomePhone": "(206) 555-9857",
    "Extension": "5467",
    "Photo": "https://js.devexpress.com/Demos/WidgetsGallery/JSDemos/images/employees/06.png",
    "Notes": "Education includes a BA in psychology from Colorado State University in 1990.  She also completed \"The Art of the Cold Call.\"  Nancy is a member of Toastmasters International.",
    "ReportsTo": 2
},
// ...
];
/* ... */
.employee-photo {
    height: 140px;
    float: left;
    padding: 0 20px 20px 0;
}

.employee-notes {
    text-align: justify;
    white-space: normal;
}

Run the code and click the Expand button in any row. You should see a detail section that contains an employee's photo and information.

Export Data to Excel

DataGrid allows users to export grid data as Excel documents. This feature requires the following third-party libraries:

To configure export operations, use the exportDataGrid(options) method from the excelExporter module. It requires a DataGrid instance and a target Excel worksheet.

This method can be called at any point in your application. The following code calls it in the DataGrid's onExporting event handler. In this code, exportDataGrid(options) exports grid data as a blob that is then saved to an XLSX file. The e.cancel parameter disables the deprecated built-in export functionality. The onExporting event handler is executed when users click the Export button. The export.enabled option adds this button to the DataGrid.

jQuery
index.html
index.js
<html>
    <head>
        <!-- ... -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.0/polyfill.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.0.1/exceljs.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.2/FileSaver.min.js"></script>

        <!-- DevExtreme scripts are referenced here -->
        <!-- ... -->
    </head>
</html>
$(function() {
    $("#dataGrid").dxDataGrid({
        // ...
        export: {
            enabled: true
        },
        onExporting: function(e) { 
            const workbook = new ExcelJS.Workbook(); 
            const worksheet = workbook.addWorksheet("Main sheet"); 
            DevExpress.excelExporter.exportDataGrid({ 
                worksheet: worksheet, 
                component: e.component,
            }).then(function() {
                workbook.xlsx.writeBuffer().then(function(buffer) { 
                    saveAs(new Blob([buffer], { type: "application/octet-stream" }), "DataGrid.xlsx"); 
                }); 
            }); 
            e.cancel = true; 
        }
    });
});
Angular
Installation command
tsconfig.app.json
app.component.html
app.component.ts
npm install --save exceljs file-saver
{
    // ...
    "compilerOptions": {
        // ...
        "paths": {
            // ...
            "exceljs": [
                "node_modules/exceljs/dist/exceljs.js"
            ]
        }
    },
    // ...
}
<dx-data-grid ...
    (onExporting)="exportGrid($event)">
    <!-- ... -->
    <dxo-export [enabled]="true"></dxo-export>
</dx-data-grid>
// ...
import { Workbook } from 'exceljs';
import saveAs from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';

// ...
export class AppComponent {
    // ...
    exportGrid(e) {
        const workbook = new Workbook(); 
        const worksheet = workbook.addWorksheet("Main sheet"); 
        exportDataGrid({ 
            worksheet: worksheet, 
            component: e.component
        }).then(function() {
            workbook.xlsx.writeBuffer().then(function(buffer: BlobPart) { 
                saveAs(new Blob([buffer], { type: "application/octet-stream" }), "DataGrid.xlsx"); 
            }); 
        }); 
        e.cancel = true; 
    }
}
Vue
Installation command
App.vue
npm install --save exceljs file-saver
<template>
    <div id="app-container">
        <DxDataGrid ...
            @exporting="exportGrid">
            <!-- ... -->
            <DxExport :enabled="true" />
        </DxDataGrid>
    </div>
</template>

<script>
import {
    DxDataGrid,
    // ...
    DxExport
} from 'devextreme-vue/data-grid';
import { Workbook } from 'exceljs';
import saveAs from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';

export default {
    components: {
        DxDataGrid,
        // ...
        DxExport
    },
    // ...
    methods: {
        exportGrid(e) {
            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"); 
                }); 
            }); 
            e.cancel = true; 
        }
    }
}
</script>

<style>
/* ... */
</style>
React
Installation command
App.js
npm install --save exceljs file-saver
import React, { useState } from 'react';
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';
import './App.css';

import {
    DataGrid,
    Column,
    // ...
    Export
} from 'devextreme-react/data-grid';

import { Workbook } from 'exceljs';
import saveAs from 'file-saver';
import { exportDataGrid } from 'devextreme/excel_exporter';
// ...

function exportGrid(e) {
    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"); 
        }); 
    });
    e.cancel = true; 
}

function App() {
    // ...
    return (
        <div className="App">
            <DataGrid ...
                onExporting={exportGrid}>
                {/* ... */}
                <Export enabled={true} />
            </DataGrid>
        </div>
    );
}

export default App;

Run the code and click the Export button in the upper-right corner. Grid data should be exported to the DataGrid.xlsx file.

For further information on the DataGrid component, refer to the following resources: