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 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 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:
$(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/21.1.12/css/dx.light.css"> <link rel="stylesheet" href="index.css"> <script type="text/javascript" src="https://cdn3.devexpress.com/jslib/21.1.12/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:
<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:
<template> <div id="app-container"> <DxDataGrid id="dataGrid"> <!-- Configuration goes here --> </DxDataGrid> </div> </template> <script> 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:
import React from 'react'; 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 property and specify the key field in the keyExpr property. If you want to use another data source type, refer to one of the following articles:
jQuery
$(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
<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
<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
import React from 'react'; 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.
Reorder Columns
To reorder grid columns, change their order in the columns array. Users can also reorder columns if you enable the allowColumnReordering property.
jQuery
$(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
<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
<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
import React from 'react'; 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 property.
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... columns: [ // ... { dataField: "BirthDate", dataType: "date", width: 100, }, { dataField: "HireDate", dataType: "date", width: 100, }, // ... ], allowColumnResizing: true, columnAutoWidth: true, }); });
Angular
<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
<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
import React from 'react'; 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 UI component's width, users can scroll the grid horizontally. If you set the columnFixing.enabled property 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 property in code. This fixes the column to the UI component's left edge. To change the position, set the fixedPosition property.
The following code fixes the FullName
column to the default position and allows users to fix and unfix columns at runtime:
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... columnFixing: { enabled: true }, columns: [{ dataField: "FullName", fixed: true }, // ... ], // ... }); });
Angular
<dx-data-grid ... > <dxi-column dataField="FullName" [fixed]="true"> </dxi-column> <!-- ... --> <dxo-column-fixing [enabled]="true"></dxo-column-fixing> </dx-data-grid>
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
import React from 'react'; 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 property to false. Hidden columns appear in the columnChooser. Users can restore hidden columns from it. To enable the column chooser. set the columnChooser.enabled property to true. If a column should not be visible even in the column chooser, simply do not declare it in the columns array.
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... columns: [ // ... { dataField: "PostalCode", visible: false }], columnChooser: { enabled: true }, }); });
Angular
<dx-data-grid ... > <!-- ... --> <dxi-column dataField="PostalCode" [visible]="false"></dxi-column> <dxo-column-chooser [enabled]="true"></dxo-column-chooser> </dx-data-grid>
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
import React from 'react'; 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 property 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 properties to specify the initial sorting settings. sortIndex applies only in multiple sorting mode.
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... columns: [{ dataField: "Country", sortOrder: "asc", }, // ... ], // sorting: { mode: "single" }, }); });
Angular
<dx-data-grid ... > <!-- ... --> <dxi-column dataField="Country" sortOrder="asc"> </dxi-column> <!-- <dxo-sorting [mode]="single"></dxo-sorting> --> </dx-data-grid>
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
import React from 'react'; 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
$(function() { $("#dataGrid").dxDataGrid({ // ... filterRow: { visible: true }, searchPanel: { visible: true }, }); });
Angular
<dx-data-grid ... > <!-- ... --> <dxo-filter-row [visible]="true"></dxo-filter-row> <dxo-search-panel [visible]="true"></dxo-search-panel> </dx-data-grid>
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
import React from 'react'; 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 property to display this UI element.
To group data in code, specify a column's groupIndex property. In this tutorial, the groupIndex is specified for the Country
column:
jQuery
$(function() { $("#dataGrid").dxDataGrid({ columns: [ // ... { dataField: "Country", // ... groupIndex: 0, }, // ... ], groupPanel: { visible: true }, }); });
Angular
<dx-data-grid ... > <!-- ... --> <dxi-column dataField="Country" ... [groupIndex]="0"> </dxi-column> <dxo-group-panel [visible]="true"></dxo-group-panel> </dx-data-grid>
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
import React from 'react'; 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 properties 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
$(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
<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
<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
import React from 'react'; 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: "Full Name is required".
Select Records
The DataGrid supports single and multiple record selection modes. Use the selection.mode property 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
$(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
<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
<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
import React, { useState } from 'react'; 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 property.
The code below configures a group summary that counts grid records in each group:
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... summary: { groupItems: [{ summaryType: "count" }] }, }); });
Angular
<dx-data-grid ... > <!-- ... --> <dxo-summary> <dxi-group-item summaryType="count"> </dxi-group-item> </dxo-summary> </dx-data-grid>
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
import React, { useState } from 'react'; 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 property to true and specify a template that is used as the detail section's content:
jQuery
$(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
<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
<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
import React, { useState } from 'react'; 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.
You can call this method 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 property adds this button to the DataGrid.
jQuery
<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('Sales'); DevExpress.excelExporter.exportDataGrid({ component: e.component, worksheet: worksheet }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'Sales.xlsx'); }); }); e.cancel = true; } }); });
Angular
npm install --save exceljs file-saver
{ // ... "compilerOptions": { // ... "paths": { // ... "exceljs": [ "node_modules/exceljs/dist/exceljs.min.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('Sales'); exportDataGrid({ worksheet: worksheet, component: e.component }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer: BlobPart) { saveAs(new Blob([buffer], { type: "application/octet-stream" }), "Sales.xlsx"); }); }); e.cancel = true; } }
Vue
npm install --save exceljs file-saver
<template> <DxDataGrid ... @exporting="exportGrid"> <!-- ... --> <DxExport :enabled="true" /> </DxDataGrid> </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('Sales'); exportDataGrid({ worksheet: worksheet, component: e.component }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: "application/octet-stream" }), "Sales.xlsx"); }); }); e.cancel = true; } } } </script> <style> /* ... */ </style>
React
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, // ... 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("Sales"); exportDataGrid({ worksheet: worksheet, component: e.component }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: "application/octet-stream" }), "Sales.xlsx"); }); }); e.cancel = true; } function App() { // ... return ( <DataGrid ... onExporting={exportGrid}> {/* ... */} <Export enabled={true} /> </DataGrid> ); } export default App;
For further information on the DataGrid component, refer to the following resources: