Angular DataGrid Properties
See Also
- Configure a Widget: Angular | Vue | React | jQuery | AngularJS | Knockout | ASP.NET MVC 5 | ASP.NET Core
accessKey
The value of this property will be passed to the accesskey
attribute of the HTML element that underlies the UI component.
allowColumnReordering
Initially, columns appear in the order specified by the columns array. If you skip specifying this array, columns will mirror the order of fields in the first object from the dataSource. You can allow a user to reorder columns at runtime by setting the allowColumnReordering property to true.
See Also
- columns[].allowReordering
allowColumnResizing
By default, the width of each column depends on the width of the UI component and the total number of columns. You can allow a user to resize the columns at runtime by setting the allowColumnResizing property to true.
See Also
- columnResizingMode
- columns[].allowResizing
- columns[].width
autoNavigateToFocusedRow
Automatically scrolls to the focused row when the focusedRowKey is changed. Incompatible with infinite scrolling mode.
cacheEnabled
When this property is set to true, data loaded once is saved in cache. Then, the UI component takes data from this cache when performing such operations as sorting, grouping, paging, etc. Caching is helpful when the data source takes significant time to load. But, consider disabling it for frequently changing data sources.
To update data in cache, call the refresh() method of the UI component or the load() method of the DataSource.
See Also
cellHintEnabled
Enables a hint that appears when a user hovers the mouse pointer over a cell with truncated content.
The cell's content may be truncated if the width of the cell's column becomes very small. In this case, when a user hovers the mouse pointer over such a cell, a hint containing the cell's value appears. To disable cell hints, assign false to the cellHintEnabled property.
columnAutoWidth
When this property is set to true, all columns adjust their width to the content.
If the UI component's overall content is narrower than the UI component's width, the columns are stretched to fit the UI component. To avoid this, set the columns.width property to "auto".
If the content is wider, the columnAutoWidth property set to true causes horizontal scrolling. You can set the allowHiding property to false for columns you want to be displayed continuously.
When the columnAutoWidth property is set to false, all columns have identical width, which in turn depends on the width of the UI component.
See Also
columnChooser
The column chooser allows a user to hide columns at runtime. To enable it, assign true to the columnChooser.enabled property.
See Also
- Column Chooser
- columns[].allowHiding
columnFixing
When the width of all columns exceeds the UI component width, horizontal scrolling appears. If specific columns should be on screen constantly regardless of how far the UI component is scrolled, allow a user to fix them at runtime using the context menu. For this, set the columnFixing.enabled property to true.
When you enable column fixing, command columns become fixed automatically.
See Also
columnHidingEnabled
Specifies whether the UI component should hide columns to adapt to the screen or container size. Ignored if allowColumnResizing is true and columnResizingMode is "widget".
This property set to true makes the UI component hide certain columns automatically if all the columns do not fit the UI component's width. Columns with low hidingPriority are hidden first. These are the rightmost (leftmost if rtlEnabled is true) columns by default. Information from hidden columns is available in an adaptive detail row.
See Also
columnResizingMode
Specifies how the UI component resizes columns. Applies only if allowColumnResizing is true.
The columnResizingMode property accepts one of the following values:
- nextColumn
When a user resizes a column, the width of the next column changes. - widget
When a user resizes a column, the width of the UI component changes.
This mode is ignored if you specify the width of any column in percent.
columns[]
By default, a column is created for each field of a data source object, but in most cases, it is redundant. To specify a set of columns to be created in a grid, assign an array specifying these columns to the columns property. Each grid column is represented in this array by an object containing column settings or by a data source field that this column is bound to. Detailed information on specifying grid columns is given in the Columns Overview article.
Column properties define the behavior and appearance of a grid column. One of the other capabilities allows you to control the sorting of column values using the allowSorting and sortOrder properties, apply a filter to grid records using the allowFiltering and filterOperations properties, and group grid records using the allowGrouping and groupIndex properties. In addition, you can change the visibility and width of a column using corresponding properties.
To get or set an property or several properties for a column at runtime, use the columnOption method with the required arguments.
See Also
columnWidth
Specifies the width for all data columns. Has a lower priority than the column.width property.
customizeColumns
All column configurations.
Use this function to make minor adjustments to automatically generated columns. You can access and modify column configurations using the function's parameter.
jQuery
$(function(){ $("#dataGrid").dxDataGrid({ // ... customizeColumns: function (columns) { columns[0].width = 100; columns[1].width = 210; } }) });
Angular
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { customizeColumns (columns) { columns[0].width = 100; columns[1].width = 210; } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
<dx-data-grid ... [customizeColumns]="customizeColumns"> </dx-data-grid>
Vue
<template> <DxDataGrid ... :customize-columns="customizeColumns"> /> </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 }, methods: { customizeColumns(columns) { columns[0].width = 100; columns[1].width = 210; } } } </script>
React
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'; class App extends React.Component { customizeColumns = (columns) => { columns[0].width = 100; columns[1].width = 210; } render() { return ( <DataGrid ... customizeColumns={this.customizeColumns} /> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... .CustomizeColumns("customizeColumns") ) <script> function customizeColumns(columns) { columns[0].width = 100; columns[1].width = 210; } </script>
customizeExportData
Since v20.1, we recommend ExcelJS-based export which does not use this property.
dataSource
If you use DevExtreme ASP.NET MVC Controls, refer to the Bind Controls to Data article.
The DataGrid works with collections of objects.
Depending on your data source, bind the DataGrid to data as follows.
Data Array
Assign the array to the dataSource property and specify the keyExpr. View DemoRead-Only Data in JSON Format
Set the dataSource property to the URL of a JSON file or service that returns JSON data. View DemoOData
Implement an ODataStore. Make sure to specify the key. View DemoWeb API, PHP, MongoDB
Use one of the following extensions to enable the server to process data according to the protocol DevExtreme UI components use:Then, use the createStore method to configure access to the server on the client as shown below. This method is part of DevExtreme.AspNet.Data.
jQuery
JavaScript$(function() { let serviceUrl = "https://url/to/my/service"; $("#dataGridContainer").dxDataGrid({ // ... dataSource: DevExpress.data.AspNet.createStore({ key: "ID", loadUrl: serviceUrl + "/GetAction", insertUrl: serviceUrl + "/InsertAction", updateUrl: serviceUrl + "/UpdateAction", deleteUrl: serviceUrl + "/DeleteAction" }) }) });
Angular
app.component.tsapp.component.htmlapp.module.tsimport { Component } from '@angular/core'; import CustomStore from 'devextreme/data/custom_store'; import { createStore } from 'devextreme-aspnet-data-nojquery'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { store: CustomStore; constructor() { let serviceUrl = "https://url/to/my/service"; this.store = createStore({ key: "ID", loadUrl: serviceUrl + "/GetAction", insertUrl: serviceUrl + "/InsertAction", updateUrl: serviceUrl + "/UpdateAction", deleteUrl: serviceUrl + "/DeleteAction" }) } }
<dx-data-grid ... [dataSource]="store"> </dx-data-grid>
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 { }
Vue
App.vue<template> <DxDataGrid ... :data-source="store" /> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import CustomStore from 'devextreme/data/custom_store'; import { createStore } from 'devextreme-aspnet-data-nojquery'; import { DxDataGrid } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid }, data() { const serviceUrl = "https://url/to/my/service"; const store = createStore({ key: "ID", loadUrl: serviceUrl + "/GetAction", insertUrl: serviceUrl + "/InsertAction", updateUrl: serviceUrl + "/UpdateAction", deleteUrl: serviceUrl + "/DeleteAction" }); return { store } } } </script>
React
App.jsimport React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import CustomStore from 'devextreme/data/custom_store'; import { createStore } from 'devextreme-aspnet-data-nojquery'; import DataGrid from 'devextreme-react/data-grid'; const serviceUrl = "https://url/to/my/service"; const store = createStore({ key: "ID", loadUrl: serviceUrl + "/GetAction", insertUrl: serviceUrl + "/InsertAction", updateUrl: serviceUrl + "/UpdateAction", deleteUrl: serviceUrl + "/DeleteAction" }); class App extends React.Component { render() { return ( <DataGrid ... dataSource={store} /> ); } } export default App;
Any other data source
Implement a CustomStore. View Demo
Regardless of the data source on the input, the DataGrid always wraps it in the DataSource object. This object allows you to sort, filter, group, and perform other data shaping operations. To get its instance, call the getDataSource() method.
Review the following notes about data binding:
Data field names cannot be equal to
this
and should not contain the following characters:.
,:
,[
, and]
.If the DataGrid UI component gets data from a server, configure remoteOperations to notify the UI component about data operations the server performs.
Features like export and selection work incorrectly with mapped data objects. Use calculated columns instead of mapping.
The stores and DataSource have methods to process and update data. However, the methods do not allow you to perform particular tasks (for example, replace the entire dataset, reconfigure data access at runtime). For such tasks, create a new array, store, or DataSource and assign it to the dataSource property as shown in the articles about changing properties in jQuery, Angular, React, and Vue.
dateSerializationFormat
Specifies the format in which date-time values should be sent to the server. Use it only if you do not specify the dataSource at design time.
Without a data source, the UI component cannot detect the date-time values' format. In this case, specify the dateSerializationFormat property that supports the following formats:
"yyyy-MM-dd"
- a local date"yyyy-MM-ddTHH:mm:ss"
- local date and time"yyyy-MM-ddTHH:mm:ssZ"
- the UTC date and time"yyyy-MM-ddTHH:mm:ssx"
- date and time with a timezone
This property applies only if the forceIsoDateParsing field is set to true in the global configuration object.
See Also
editing
The UI component can allow a user to add, update and delete data. To control which of these operations are allowed, use the allowAdding, allowUpdating and allowDeleting properties. Editing can be carried out in different modes, which are detailed in the mode property's description.
See Also
elementAttr
Specifies the global attributes to be attached to the UI component's container element.
jQuery
$(function(){ $("#dataGridContainer").dxDataGrid({ // ... elementAttr: { id: "elementId", class: "class-name" } }); });
Angular
<dx-data-grid ... [elementAttr]="{ id: 'elementId', class: 'class-name' }"> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid ... :element-attr="dataGridAttributes"> </DxDataGrid> </template> <script> import DxDataGrid from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid }, data() { return { dataGridAttributes: { id: 'elementId', class: 'class-name' } } } } </script>
React
import React from 'react'; import DataGrid from 'devextreme-react/data-grid'; class App extends React.Component { dataGridAttributes = { id: 'elementId', class: 'class-name' } render() { return ( <DataGrid ... elementAttr={this.dataGridAttributes}> </DataGrid> ); } } export default App;
errorRowEnabled
The error row displays data-related errors that may occur on the server during the UI component's runtime. Setting this property to false hides the error row, but the errors can still be viewed in the browser's console.
See Also
export
A user can click the Export button to save an Excel file with the exported data. Data types, sorting, filtering, and grouping settings are maintained.
The following instructions show how to enable and configure client-side export:
Install or reference the required libraries
This feature requires ExcelJS v4+ and FileSaver v2.0.2+.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.1.1/exceljs.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.2/FileSaver.min.js"></script> <!-- reference the DevExtreme sources here --> </head>
Angular
Installation commandtsconfig.app.jsonnpm install --save exceljs file-saver
"compilerOptions": { // ... "paths": { // ... "exceljs": [ "node_modules/exceljs/dist/exceljs.js" ] } }
Vue
npm install --save exceljs file-saver
React
npm install --save exceljs file-saver
Enable the export UI
Set the export.enabled property to true. This property enables export for all columns. Set a column's allowExporting property to false to prevent it from being exported:jQuery
JavaScript$(function () { $("#dataGridContainer").dxDataGrid({ export: { enabled: true }, columns: [{ ... allowExporting: false }, // ... ] }); });
Angular
app.component.htmlapp.component.tsapp.module.ts<dx-data-grid ... > <dxo-export [enabled]="true"></dxo-export> <dxi-column ... [allowExporting]="false"> </dxi-column> </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 { }
Vue
App.vue<template> <DxDataGrid ... > <DxExport :enabled="true" /> <DxColumn ... :allow-exporting="false" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxExport, DxColumn } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxExport, DxColumn } } </script>
React
App.jsimport React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid, { Export, Column } from 'devextreme-react/data-grid'; class App extends React.Component { render() { return ( <DataGrid ... > <Export enabled={true} /> <Column ... allowExporting={false} /> </DataGrid> ); } } export default App;
Export the DataGrid
Implement the onExporting handler and call the exportDataGrid(options) method in it. In the code below, this method exports the DataGrid as is, but you can use ExportDataGridProps to configure export settings, including cell customization. The DataGrid is exported to an Excel worksheet that is created using the ExcelJS API. To save the Excel document, call the FileSaver's saveAs method. Thee.cancel
parameter disables the deprecated built-in export implementation with fewer capabilities.jQuery
JavaScript$('#gridContainer').dxDataGrid({ export: { enabled: true }, onExporting: function(e) { var workbook = new ExcelJS.Workbook(); var worksheet = workbook.addWorksheet('Main sheet'); DevExpress.excelExporter.exportDataGrid({ worksheet: worksheet, component: e.component, customizeCell: function(options) { var excelCell = options; excelCell.font = { name: 'Arial', size: 12 }; excelCell.alignment = { horizontal: 'left' }; } }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }); e.cancel = true; } });
Angular
app.component.htmlapp.component.tsapp.module.ts<dx-data-grid ... (onExporting)="onExporting($event)"> <dxo-export [enabled]="true"></dxo-export> </dx-data-grid>
import { Component } from '@angular/core'; import { exportDataGrid } from 'devextreme/excel_exporter'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { onExporting(e) { const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Main sheet'); exportDataGrid({ component: e.component, worksheet: worksheet, customizeCell: function(options) { const excelCell = options; excelCell.font = { name: 'Arial', size: 12 }; excelCell.alignment = { horizontal: 'left' }; } }).then(function() { workbook.xlsx.writeBuffer() .then(function(buffer: BlobPart) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }); e.cancel = true; } }
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 { }
Vue
App.vue<template> <DxDataGrid ... @exporting="onExporting"> <DxExport :enabled="true" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxExport } from 'devextreme-vue/data-grid'; import { exportDataGrid } from 'devextreme/excel_exporter'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; export default { components: { DxDataGrid, DxExport }, methods: { onExporting(e) { const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Main sheet'); exportDataGrid({ component: e.component, worksheet: worksheet, customizeCell: function(options) { const excelCell = options; excelCell.font = { name: 'Arial', size: 12 }; excelCell.alignment = { horizontal: 'left' }; } }).then(function() { workbook.xlsx.writeBuffer() .then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }); e.cancel = true; } } } </script>
React
App.jsimport React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; import DataGrid, { Export } from 'devextreme-react/data-grid'; import { exportDataGrid } from 'devextreme/excel_exporter'; class App extends React.Component { render() { return ( <DataGrid ... onExporting={this.onExporting}> <Export enabled={true} /> </DataGrid> ); } onExporting(e) { const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Main sheet'); exportDataGrid({ component: e.component, worksheet: worksheet, customizeCell: function(options) { const excelCell = options; excelCell.font = { name: 'Arial', size: 12 }; excelCell.alignment = { horizontal: 'left' }; } }).then(function() { workbook.xlsx.writeBuffer() .then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }); e.cancel = true; } } export default App;
The following restrictions apply when users export DataGrid:
Only XLSX files are supported.
Excel limits the number of grouping levels to 7, while in the DataGrid it is unlimited.
Only visible columns are exported. See the onExporting property description for a workaround.
Detail rows are not exported.
Group rows are always exported in an expanded state and the isExpanded property is ignored.
Customizations made in the cellTemplate, groupCellTemplate, headerCellTemplate, and rowTemplate are omitted, but you can recreate them in the exported file using the ExcelJS API. Use the customizeCell function to do this. View Demo
Data mapping is ignored. Use calculated columns instead.
filterBuilder
See the FilterBuilder configuration for properties that you can specify in this object.
See Also
filterBuilderPopup
Configures the popup in which the integrated filter builder is shown.
See the Popup configuration for properties that you can specify in this object.
See Also
filterPanel
The filter panel displays the applied filter expression.
Clicking on the filter expression opens the filter builder.
If you change the filter expression in the filter panel or filter builder, the changes are reflected in the filter row and header filter, and vice versa. You can disable this synchronization by setting the filterSyncEnabled property to false. In this case, the filter panel remains synchronized with the filter builder.
See Also
filterRow
The filter row allows a user to filter data by values of individual columns.
Each cell in the filter row contains a magnifying glass icon, pausing on which opens a drop-down list with filters available for the column.
To make the filter row visible, assign true to the filterRow.visible property.
See Also
filterSyncEnabled
Specifies whether to synchronize the filter row, header filter, and filter builder. The synchronized filter expression is stored in the filterValue property.
Synchronization is enabled if the filter panel is visible. When it is enabled, check that each column that allows filtering has the dataField or name property specified.
filterValue
If filterSyncEnabled is true, the filter expression includes a combination of the filter row, header filter, and filter builder filters. Otherwise, it contains only the filter builder filter.
The filter expression can contain the following operations: "=", "<>", "<", ">", "<=", ">=", "between", "contains", "notcontains", "startswith", "endswith", "anyof", "noneof", and the filter builder's custom operations. Use "anyof" and "noneof" to select and clear the selection of items in the header filter's popup menu. In the following code, "anyof" is used to select items with IDs 500
and 700
:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... filterSyncEnabled: true, headerFilter: { visible: true }, filterValue: ["ID", "anyof", [500, 700]], }) });
Angular
<dx-data-grid ... [filterSyncEnabled]="true" [filterValue]="['ID', 'anyof', [500, 700]]"> <dxo-header-filter [visible]="true"> </dxo-header-filter> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid ... :filter-sync-enabled="true" :filter-value="filterValue"> <DxHeaderFilter :visible="true" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DxDataGrid, { DxHeaderFilter, // ... } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxHeaderFilter, // ... }, data() { return { filterValue: ['ID', 'anyof', [500, 700]] } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid, { HeaderFilter, // ... } from 'devextreme-react/data-grid'; const filterValue = ['ID', 'anyof', [500, 700]]; class App extends React.Component { render() { return ( <DataGrid ... filterSyncEnabled={true} defaultFilterValue={filterValue}> <HeaderFilter visible={true} /> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... .FilterSyncEnabled(true) .HeaderFilter(hf => hf.Visible(true)) .FilterValue("['ID', 'anyof', [500, 700]]") )
If a column's groupInterval property is set, the "anyof" and "noneof" operations for this column accept the beginning of intervals instead of exact values:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... headerFilter: { visible: true }, filterValue: ["ID", "anyof", [500, 700]], // Filter intervals are 500-600 and 700-800 columns: [{ dataField: "ID", dataType: "number", headerFilter: { groupInterval: 100 } }, // ... ] }) });
Angular
<dx-data-grid ... <!-- Filter intervals are 500-600 and 700-800 --> [(filterValue)]="['ID', 'anyof', [500, 700]]"> <dxo-header-filter [visible]="true"> </dxo-header-filter> <dxi-column dataField="ID" dataType="number"> <dxo-header-filter [groupInterval]="100"> </dxo-header-filter> </dxi-column> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid ... <!-- Filter intervals are 500-600 and 700-800 --> :filter-value="filterValue"> <DxHeaderFilter :visible="true" /> <DxColumn data-field="ID" data-type="number"> <DxColumnHeaderFilter :group-interval="100" /> </DxColumn> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DxDataGrid, { DxColumn, DxHeaderFilter, DxColumnHeaderFilter, // ... } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxColumn, DxHeaderFilter, DxColumnHeaderFilter, // ... }, data() { return { filterValue: ['ID', 'anyof', [500, 700]] } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid, { Column, HeaderFilter, ColumnHeaderFilter, // ... } from 'devextreme-react/data-grid'; const filterValue = ['ID', 'anyof', [500, 700]]; class App extends React.Component { render() { return ( <DataGrid ... {/* Filter intervals are 500-600 and 700-800 */} defaultFilterValue={filterValue}> <HeaderFilter visible={true} /> <Column dataField="ID" dataType="number"> <ColumnHeaderFilter groupInterval={100} /> </Column> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... // Filter intervals are 500-600 and 700-800 .HeaderFilter(headerFilter => headerFilter.Visible(true)) .FilterValue("['ID', 'anyof', [500, 700]]") .Columns(columns => { columns.AddFor(m => m.ID) .DataType(GridColumnDataType.Number) .HeaderFilter(hf => hf.GroupInterval(100)); // ... }) )
See Also
focusedColumnIndex
The index of the column that contains the focused data cell. This index is taken from the columns array.
Unlike banded columns, Band columns cannot be focused.
The default index, -1, means that no column is focused.
See Also
focusedRowEnabled
When this property is set to true, the following applies:
- Rows are initially sorted by keys if any field of remoteOperations is true.
- The row with focusedRowIndex or focusedRowKey is highlighted.
- When the data row area is focused, this row is focused and the area is scrolled down to it.
- The onFocusedRowChanging and onFocusedRowChanged functions become active.
See Also
focusedRowIndex
Specifies or indicates the focused data row's index. Use this property when focusedRowEnabled is true.
The focused row has a key and index on a page. When the pager is used for navigation, the focused row's index persists from page to page, but corresponds to a different row with a different key on each page.
The default index, -1, means that no row is focused.
The focusedRowKey takes precedence over the focusedRowIndex when both are specified.
See Also
focusedRowKey
Specifies initially or currently focused grid row's key. Use it when focusedRowEnabled is true.
The focused row has a key and index on a page. When the pager is used for navigation, the focused row's index persists from page to page but corresponds to a different row with a different key on each page.
In the DataGrid, group rows can also be focused. See the Group Index and Key topic for more information on how group keys are formed.
See Also
groupPanel
Configures the group panel.
Data in DataGrid can be grouped by one column or by several. Once a column is used for grouping, it is added to the group panel.
By default, the group panel is hidden. To make it visible, set the groupPanel.visible property to true. Alternatively, the visibility of the group panel can depend on the device's screen size. To accomplish this behavior, set the visible property to "auto".
In case you need to show the group panel, but make it irresponsive, assign false to the groupPanel.allowColumnDragging property. This is useful, for instance, when grid records are grouped initially and when the user needs to know about that grouping, but must not be able to change it.
See Also
- Grouping
- grouping.contextMenuEnabled - enables the user to group data using the context menu.
- columns[].allowGrouping - disallows grouping for an individual column.
headerFilter
A header filter allows a user to filter values in an individual column by including/excluding them in/from the applied filter. A click on a header filter icon invokes a popup menu with all unique values in the column. By selecting or clearing the selection of values in this menu, the user includes/excludes them in/from the filter.
To make header filter icons visible, assign true to the headerFilter.visible property.
A header filter's popup menu lists all column values. If they are numbers or dates, you can group them using the groupInterval property in the column's headerFilter. You can also provide a custom data source for a header filter using the dataSource property.
The user's filtering preferences are saved in the filterValues property. The header filter's Select All checkbox changes the filterType property.
See Also
height
This property accepts a value of one of the following types:
Number
The height in pixels.String
A CSS-accepted measurement of height. For example,"55px"
,"80%"
,"inherit"
.Function
A function returning either of the above. For example:JavaScriptheight: function() { return window.innerHeight / 1.5; }
highlightChanges
Specifies whether to highlight rows and cells with edited data. repaintChangesOnly should be true.
You can change the following CSS rules and classes that control highlighting:
@keyframes dx-datagrid-highlight-change { from { background-color: #efefef; } 50% { background-color: #efefef; } } .dx-datagrid-cell-updated-animation { animation: dx-datagrid-highlight-change 1s; } .dx-datagrid-row-inserted-animation { animation: dx-datagrid-highlight-change 1s; }
keyExpr
Specifies the key property (or properties) that provide(s) key values to access data items. Each key value must be unique. This property applies only if data is a simple array.
loadPanel
The load panel is displayed while the UI component loads data. It consists of a loading indicator and text, both placed on a pane.
Since the load panel is, in fact, the DevExtreme LoadPanel UI component, the loadPanel object can contain any properties of this UI component along with properties described here.
See Also
masterDetail
Allows you to build a master-detail interface in the grid.
In DataGrid, a master-detail interface supplies a usual data row with an expandable section that contains the details on this data row. In that case, the data row is called "master row", while the section is called "detail section".
To enable the master-detail interface, assign true to the masterDetail.enabled property. After that, specify the template for detail sections using the masterDetail.template property. Templates allow you to place virtually anything into the detail sections. For example, you can display another DataGrid or any other UI component there. For more information on specifying the template for the detail sections, see the template property description.
See Also
onAdaptiveDetailRowPreparing
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
formOptions |
The properties of the Form UI component. |
|
model |
Model data. Available only if you use Knockout. |
Adaptive detail rows display information from columns that were hidden when the UI component adapted to the screen or container size. Each adaptive detail row contains the Form UI component that you can customize within the onAdaptiveDetailRowPreparing function using the formOptions object. Refer to the Form Configuration section for details on properties of the Form UI component.
The following Form properties cannot be specified using formOptions:
- template
- editorType
- any event handler (properties whose name starts with "on...")
See Also
- columnHidingEnabled
- columns[].hidingPriority
- Adaptability
onCellClick
A function that is executed when a cell is clicked or tapped. Executed before onRowClick.
Name | Type | Description |
---|---|---|
cellElement |
The cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
column |
This column's configuration. |
|
columnIndex |
The index of the column to which the cell belongs. For details on indexes, see the Column and Row Indexes topic. |
|
component |
The UI component's instance. |
|
data |
The data of the row to which the cell belongs. |
|
displayValue | any |
The cell's displayed value. Differs from the value field only when the column to which the clicked cell belongs uses lookup. |
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
jQueryEvent |
Use 'event' instead. The jQuery event that caused the handler execution. Deprecated in favor of the event field. |
|
key | any |
The row's key. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
|
row |
The row properties. |
|
rowIndex |
The index of the row to which the cell belongs. Refer to Column and Row Indexes for more information. |
|
rowType |
The type of the row to which the clicked cell belongs. |
|
text |
The cell's formatted value converted to a string. |
|
value | any |
The cell's raw value. |
onCellDblClick
A function that is executed when a cell is double-clicked or double-tapped. Executed before onRowDblClick.
Name | Type | Description |
---|---|---|
cellElement |
The cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
column |
The column's configuration. |
|
columnIndex |
The index of the column the cell belongs to. For details on indexes, see the Column and Row Indexes topic. |
|
component |
The UI component's instance. |
|
data |
The data of the row the cell belongs to. Available if the rowType is "data", "detail", or "detailAdaptive". |
|
displayValue | any |
The value displayed in the cell. Available if the rowType is "data" or "group". |
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
key | any |
The row's key or a group row's key. Available if the rowType is "data", "detail", "detailAdaptive", or "group". |
model |
Model data. Available only if you use Knockout. |
|
row |
The row's properties. Available if the rowType is "data", "detail", "detailAdaptive", or "group". |
|
rowIndex |
The index of the row the cell belongs to. |
|
rowType |
The row's type. |
|
text |
The cell's formatted value converted to a string. Available if the rowType is "data" or "group". |
|
value | any |
The cell's raw value. Available if the rowType is "data" or "group". |
onCellHoverChanged
Name | Type | Description |
---|---|---|
cellElement |
The cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
column |
This column's configuration. |
|
columnIndex |
The index of the column to which the cell belongs. For details on indexes, see the Column and Row Indexes topic. |
|
component |
The UI component's instance. |
|
data |
The data of the row to which the cell belongs. |
|
displayValue | any |
The cell's displayed value. Differs from the value field only when the column to which the current cell belongs uses lookup. |
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
eventType |
Indicates whether the pointer entered or left the cell. Can be either "mouseover" or "mouseout". |
|
key | any |
The row's key. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
|
row |
The row properties. |
|
rowIndex |
The row's index. Refer to Column and Row Indexes for more information. |
|
rowType |
The row's type. |
|
text |
The cell's formatted value converted to a string. |
|
value | any |
The cell's raw value. |
onCellPrepared
Name | Type | Description |
---|---|---|
cellElement |
The cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
column |
This column's configuration. |
|
columnIndex |
The visible column index described in the following topic: Column and Row Indexes. |
|
component |
The UI component's instance. |
|
data |
The data of the row to which the cell belongs. Unavailable if rowType is "header", "filter", or "totalFooter". |
|
displayValue | any |
The cell's displayed value. Differs from the value field only when the column to which the prepared cell belongs uses lookup. |
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
isExpanded |
Indicates whether the row is expanded or collapsed. Unavailable if rowType is "header", "filter", or "totalFooter". |
|
isNewRow |
Indicates that the row is added, but not yet saved. Available if rowType is "data". |
|
isSelected |
Indicates whether the row is selected. |
|
key | any |
The row's key. Unavailable if rowType is "header", "filter", or "totalFooter". |
model |
Model data. Available only if you use Knockout. |
|
oldValue | any |
The cell's previous raw value. Defined only if repaintChangesOnly is true. |
row |
The row properties. |
|
rowIndex |
The row's index. Refer to Column and Row Indexes for more information. |
|
rowType |
The row's type. |
|
text |
The cell's formatted value converted to a string. |
|
value | any |
The cell's raw value. |
watch |
Allows you to track a variable and execute actions when it changes. Applies when repaintChangesOnly is true.
|
In the following code, the onCellPrepared function is used to change a ProductName
's color depending on the Amount
of sold products. You can paste this code in the Real-Time Updates demo and see how it works.
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... repaintChangesOnly: true, onCellPrepared: function(e) { if(e.rowType === "data" && e.column.dataField === "ProductName") { e.cellElement.css("color", e.data.Amount >= 10000 ? "green" : "red"); // Tracks the `Amount` data field e.watch(function() { return e.data.Amount; }, function() { e.cellElement.css("color", e.data.Amount >= 10000 ? "green" : "red"); }) } } }) })
Angular
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { onCellPrepared(e) { if(e.rowType === "data" && e.column.dataField === "ProductName") { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; // Tracks the `Amount` data field e.watch(function() { return e.data.Amount; }, function() { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; }) } } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
<dx-data-grid ... [repaintChangesOnly]="true" (onCellPrepared)="onCellPrepared($event)"> </dx-data-grid>
Vue
<template> <DxDataGrid :repaint-changes-only="true" @cell-prepared="onCellPrepared" /> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid }, methods: { onCellPrepared(e) { if(e.rowType === "data" && e.column.dataField === "ProductName") { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; // Tracks the `Amount` data field e.watch(function() { return e.data.Amount; }, function() { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; }) } } } } </script>
React
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'; class App extends React.Component { // ... render() { return ( <DataGrid repaintChangesOnly={true} onCellPrepared={this.onCellPrepared} /> ); } onCellPrepared = (e) => { if(e.rowType === "data" && e.column.dataField === "ProductName") { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; // Tracks the `Amount` data field e.watch(function() { return e.data.Amount; }, function() { e.cellElement.style.color = e.data.Amount >= 10000 ? "green" : "red"; }) } } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() .ID("dataGridContainer") // ... .RepaintChangesOnly(true) .OnCellPrepared("dataGrid_cellPrepared_handler") ) <script> function dataGrid_cellPrepared_handler(e) { if (e.rowType === "data" && e.column.dataField === "ProductName") { e.cellElement.css("color", e.data.Amount >= 10000 ? "green" : "red"); // Tracks the `Amount` data field e.watch(function() { return e.data.Amount; }, function() { e.cellElement.css("color", e.data.Amount >= 10000 ? "green" : "red"); }) } } </script>
See Also
onContentReady
A function that is executed when the UI component's content is ready and each time the content is changed.
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only when using Knockout. |
onContextMenuPreparing
Name | Type | Description |
---|---|---|
column |
This column's configuration. |
|
columnIndex |
The index of the column on which the context menu is invoked. For details on indexes, see the following help topic: Column and Row Indexes. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
items |
Items to be displayed in the context menu. Their structure is described in the items property description. Each item also contains the onItemClick event handler, which allows you to access the clicked or tapped item's data. |
|
model |
Model data. Available only if you use Knockout. |
|
row |
The row properties. |
|
rowIndex |
The index of the row on which the context menu is invoked. Refer to the following help topic for more information: Column and Row Indexes. |
|
target |
The name of the element on which the context menu is invoked: "headerPanel", "header", "content", or "footer". This field is read-only. |
|
targetElement |
The grid element's container. It is an HTML Element or a jQuery Element when you use jQuery. |
In the following code, the onContextMenuPreparing function adds a custom item to the context menu invoked when a user right-clicks any column header:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... onContextMenuPreparing: function(e) { if (e.target == "header") { // e.items can be undefined if (!e.items) e.items = []; // Add a custom menu item e.items.push({ text: "Log Column Caption", onItemClick: function() { console.log(e.column.caption); } }); } } }); });
Angular
<dx-data-grid ... (onContextMenuPreparing)="addMenuItems($event)"> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { addMenuItems(e) { if (e.target == 'header') { // e.items can be undefined if (!e.items) e.items = []; // Add a custom menu item e.items.push({ text: 'Log Column Caption', onItemClick: () => { console.log(e.column.caption); } }); } } }
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 { }
Vue
<template> <DxDataGrid ... @context-menu-preparing="addMenuItems"> </DxDataGrid> </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 }, data() { return { // ... } }, methods: { addMenuItems(e) { if (e.target == 'header') { // e.items can be undefined if (!e.items) e.items = []; // Add a custom menu item e.items.push({ text: 'Log Column Caption', onItemClick: () => { console.log(e.column.caption); } }); } } } } </script>
React
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'; class App extends React.Component { addMenuItems(e) { if (e.target == 'header') { // e.items can be undefined if (!e.items) e.items = []; // Add a custom menu item e.items.push({ text: 'Log Column Caption', onItemClick: () => { console.log(e.column.caption); } }); } } render() { return ( <DataGrid ... onContextMenuPreparing={this.addMenuItems}> </DataGrid> ); } } export default App;
onDataErrorOccurred
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
error |
The standard Error object that defines the error. |
|
model |
Model data. Available only if you use Knockout. |
onDisposing
A function that is executed before the UI component is disposed of.
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
onEditingStart
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel row editing. |
|
column |
The configuration of the column whose cell is switching to the editing state. Available in the "cell" and "batch" editing modes. |
|
component |
The UI component's instance. |
|
data |
The data of a row to be edited. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The row's key. The key of an added but not yet saved row is undefined. |
model |
Model data. Available only if Knockout is used. |
If the editing.mode is "batch" or "cell", this function is executed while the UI component renders columns of boolean
dataType and other columns whose showEditorAlways property is true.
onEditorPrepared
A function that is executed after an editor is created. Not executed for cells with an editCellTemplate.
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
dataField |
The name of the field that provides data for the column the editor belongs to. |
|
disabled |
Indicates whether the editor is disabled. |
|
editorElement |
The editor's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Only available when using Knockout. |
|
parentType |
The editor's location. One of "dataRow", "filterRow", "headerRow" or "searchPanel". |
|
readOnly |
Indicates whether the editor is read-only. |
|
row |
The properties of the row the editor belongs to. |
|
rtlEnabled |
Indicates whether the editor uses right-to-left representation. |
|
setValue(newValue, newText) | any |
A method you should call to change the cell value and, optionally, the displayed value after the editor's value is changed. |
updateValueTimeout |
Gets and sets the delay between when a user stops typing a filter value and the change is applied. Available if the parentType is "filterRow" or "searchPanel". |
|
value | any |
The editor's value. |
width |
The editor's width; equals null for all editors except for those whose parentType equals "searchPanel". |
onEditorPreparing
A function used to customize a cell's editor. Not executed for cells with an editCellTemplate.
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel the editor's creation. |
|
component |
The UI component's instance. |
|
dataField |
The name of the field that provides data for the column's editor. |
|
disabled |
Indicates whether the editor is disabled. |
|
editorElement |
The editor's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
editorName |
Allows you to change the editor. Accepts names of DevExtreme UI components only, for example, "dxTextBox". |
|
editorOptions |
Gets and sets the editor's configuration. editorOptions specified in the editing.form object have precedence over this parameter. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
parentType |
The editor's location. One of "dataRow", "filterRow", "headerRow" or "searchPanel". |
|
readOnly |
Indicates whether the editor is read-only. |
|
row |
The properties of the row's editor. |
|
rtlEnabled |
Indicates whether the editor uses right-to-left representation. |
|
setValue(newValue, newText) | any |
A method you should call to change the cell value and, optionally, the displayed value after the editor's value is changed. |
updateValueTimeout |
Gets and sets the delay between when a user stops typing a filter value and the change is applied. Available if the parentType is "filterRow" or "searchPanel". |
|
value | any |
The editor's value. This field is read-only. To change the editor's value, use the setValue(newValue, newText) function parameter. |
width |
The editor's width; equals null for all editors except for those whose parentType equals "searchPanel". |
Use this function to:
Override the default editor's onValueChanged handler. For other default editor customizations, use editorOptions.
jQuery
index.js$(function() { $("#dataGridContainer").dxDataGrid({ // ... onEditorPreparing: function(e) { if (e.dataField === "requiredDataField" && e.parentType === "dataRow") { const defaultValueChangeHandler = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = function(args) { // Override the default handler // ... // Custom commands go here // ... // If you want to modify the editor value, call the setValue function: // e.setValue(newValue); // Otherwise, call the default handler: defaultValueChangeHandler(args); } } } }); });
Angular
app.component.htmlapp.component.tsapp.module.ts<dx-data-grid ... (onEditorPreparing)="overrideOnValueChanged($event)"> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { overrideOnValueChanged(e) { if (e.dataField === 'requiredDataField' && e.parentType === 'dataRow') { const defaultValueChangeHandler = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = function (args) { // Override the default handler // ... // Custom commands go here // ... // If you want to modify the editor value, call the setValue function: // e.setValue(newValue); // Otherwise, call the default handler: defaultValueChangeHandler(args); } } } }
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 { }
Vue
App.vue<template> <DxDataGrid ... @editor-preparing="overrideOnValueChanged"> </DxDataGrid> </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 }, // ... methods: { overrideOnValueChanged(e) { if (e.dataField === 'requiredDataField' && e.parentType === 'dataRow') { const defaultValueChangeHandler = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = function (args) { // Override the default handler // ... // Custom commands go here // ... // If you want to modify the editor value, call the setValue function: // e.setValue(newValue); // Otherwise, call the default handler: defaultValueChangeHandler(args); } } } } } </script>
React
App.jsimport React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid from 'devextreme-react/data-grid'; class App extends React.Component { overrideOnValueChanged(e) { if (e.dataField === 'requiredDataField' && e.parentType === 'dataRow') { const defaultValueChangeHandler = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = function (args) { // Override the default handler // ... // Custom commands go here // ... // If you want to modify the editor value, call the setValue function: // e.setValue(newValue); // Otherwise, call the default handler: defaultValueChangeHandler(args); } } } render() { return ( <DataGrid ... onEditorPreparing={this.overrideOnValueChanged}> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
Razor C#@(Html.DevExtreme().DataGrid() // ... .OnEditorPreparing("overrideOnValueChanged") ) <script type="text/javascript"> function overrideOnValueChanged(e) { if (e.dataField === "requiredDataField" && e.parentType === "dataRow") { const defaultValueChangeHandler = e.editorOptions.onValueChanged; e.editorOptions.onValueChanged = function(args) { // Override the default handler // ... // Custom commands go here // ... // If you want to modify the editor value, call the setValue function: // e.setValue(newValue); // Otherwise, call the default handler: defaultValueChangeHandler(args); } } } </script>
Customize editors used in the search panel, filter row, and selection column.
Use the parentType function parameter to check if the editor being customized belongs to one of these UI elements.Implement other customization cases.
See Also
- columns[].showEditorAlways
onExported
Since v20.1, we recommend ExcelJS-based export which does not use this property.
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if Knockout is used. |
You can use this function with the onExporting function to adjust columns before exporting. See an example in the onExporting description.
See Also
onExporting
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel exporting data. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
fileName |
The name of the file where grid data is about to be exported. |
|
model |
Model data. Available only if Knockout is used. |
You can use this function to adjust column properties before export. In the following code, the column.visible property's value is changed to export the hidden ID
column.
jQuery
$(function() { $('#gridContainer').dxDataGrid({ // ... export: { enabled: true }, columns: [{ dataField: 'ID', visible: false }, { // ... }], onExporting: function(e) { e.component.beginUpdate(); e.component.columnOption('ID', 'visible', true); var workbook = new ExcelJS.Workbook(); var worksheet = workbook.addWorksheet('Main sheet'); DevExpress.excelExporter.exportDataGrid({ component: e.component, worksheet: worksheet }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }).then(function() { e.component.columnOption('ID', 'visible', false); e.component.endUpdate(); }); e.cancel = true; } }); });
Angular
<dx-data-grid ... (onExporting)="onExporting($event)"> <dxo-export [enabled]="true"></dxo-export> <dxi-column dataField="ID" [visible]="false"></dxi-column> </dx-data-grid>
import { Component } from '@angular/core'; import { exportDataGrid } from 'devextreme/excel_exporter'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { onExporting(e) { e.component.beginUpdate(); e.component.columnOption('ID', 'visible', true); const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Employees'); exportDataGrid({ component: e.component, worksheet: worksheet }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer: BlobPart) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }).then(function() { e.component.columnOption('ID', 'visible', false); e.component.endUpdate(); }); e.cancel = true; } }
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 { }
Vue
<template> <DxDataGrid ... @exporting="onExporting"> <DxExport :enabled="true" /> <DxColumn data-field="ID" :visible="false" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxExport, DxColumn } from 'devextreme-vue/data-grid'; import { exportDataGrid } from 'devextreme/excel_exporter'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; export default { components: { DxDataGrid, DxExport, DxColumn }, methods: { onExporting(e) { e.component.beginUpdate(); e.component.columnOption('ID', 'visible', true); const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Employees'); exportDataGrid({ component: e.component, worksheet: worksheet }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }).then(function() { e.component.columnOption('ID', 'visible', false); e.component.endUpdate(); }); e.cancel = true; } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { Workbook } from 'exceljs'; import saveAs from 'file-saver'; import DataGrid, { Export, Column } from 'devextreme-react/data-grid'; import { exportDataGrid } from 'devextreme/excel_exporter'; class App extends React.Component { render() { return ( <DataGrid ... onExporting={this.onExporting}> <Export enabled={true} /> <Column dataField="ID" visible={false} /> </DataGrid> ); } onExporting(e) { e.component.beginUpdate(); e.component.columnOption('ID', 'visible', true); const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Employees'); exportDataGrid({ component: e.component, worksheet: worksheet }).then(function() { workbook.xlsx.writeBuffer().then(function(buffer) { saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); }); }).then(function() { e.component.columnOption('ID', 'visible', false); e.component.endUpdate(); }); e.cancel = true; } } export default App;
See Also
onFileSaving
Since v20.1, we recommend ExcelJS-based export which does not use this property.
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel file saving. |
|
component |
The UI component's instance. |
|
data |
Exported data as a BLOB. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
fileName |
The name of the file to be saved. |
|
format |
The format of this file. Equals "EXCEL" for an Excel file. |
onFocusedCellChanged
A function that is executed after the focused cell changes. Applies only to cells in data or group rows.
Name | Type | Description |
---|---|---|
cellElement |
The focused cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
column |
The column's properties. |
|
columnIndex |
The index of the cell's column. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
row |
The row's properties. |
|
rowIndex |
The index of the cell's row. |
onFocusedCellChanging
A function that is executed before the focused cell changes. Applies only to cells in data or group rows.
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel focusing a new cell. |
|
cellElement |
The to-be-focused cell's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
columns |
The visible columns' properties. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
isHighlighted |
true if the cell is highlighted; otherwise false, even if the cell's row is highlighted. |
|
model |
Model data. Available only if you use Knockout. |
|
newColumnIndex |
The index of the column the cell that should be focused belongs to. |
|
newRowIndex |
The index of the row the cell that should be focused belongs to. |
|
prevColumnIndex |
The index of the previously focused cell's column. |
|
prevRowIndex |
The index of the previously focused cell's row. |
|
rows |
The visible rows' properties. |
In the following code, the onFocusedCellChanging function is used to customize keyboard navigation within a row. The cell navigation is looped in a single row because focus moves to the row's first cell after reaching the last cell and vice versa:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... onFocusedCellChanging: function (e) { if (e.newColumnIndex == e.prevColumnIndex) { e.newColumnIndex = (e.newColumnIndex == 0 ? e.columns.length - 1 : 0) } } }); });
Angular
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { onFocusedCellChanging (e) { if (e.newColumnIndex == e.prevColumnIndex) { e.newColumnIndex = (e.newColumnIndex == 0 ? e.columns.length - 1 : 0) } } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
<dx-data-grid ... (onFocusedCellChanging)="onFocusedCellChanging($event)"> </dx-data-grid>
Vue
<template> <DxDataGrid ... @focused-cell-changing="onFocusedCellChanging" > </DxDataGrid> </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 }, methods: { onFocusedCellChanging(e) { if (e.newColumnIndex == e.prevColumnIndex) { e.newColumnIndex = (e.newColumnIndex == 0 ? e.columns.length - 1 : 0); } } } } </script>
React
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'; class App extends React.Component { render() { return ( <DataGrid ... onFocusedCellChanging={this.onFocusedCellChanging} > </DataGrid> ); } onFocusedCellChanging(e) { if (e.newColumnIndex == e.prevColumnIndex) { e.newColumnIndex = (e.newColumnIndex == 0 ? e.columns.length - 1 : 0); } } } export default App;
See Also
onFocusedRowChanged
A function that is executed after the focused row changes. Applies only to data or group rows. focusedRowEnabled should be true.
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
row |
The row's properties. |
|
rowElement |
The focused row's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
rowIndex |
The row's index. |
onFocusedRowChanging
A function that is executed before the focused row changes. Applies only to data or group rows. focusedRowEnabled should be true.
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel focusing a new row. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
model |
Model data. Available only if you use Knockout. |
|
newRowIndex |
The index of the row to be focused. |
|
prevRowIndex |
The index of the previously focused row. |
|
rowElement |
The to-be-focused row's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
rows |
The visible rows' properties. |
onInitialized
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
onInitNewRow
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
data |
The data of the inserted row; initially empty. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
promise |
Assign a Promise to this field to perform an asynchronous operation, such as a request to a server. |
You can use this function to populate a new row with data. Add fields to the data object that correspond to the data source object's fields. Note that the data object can omit some fields from the data source object. Add only those fields that should initialize specific cells of a new row.
In the following code, the onInitNewRow function is used to provide default values for the new row's ID
, hireDate
, and position
cells. The promise parameter is used to obtain values for the ID
and position
cell values asynchronously:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ dataSource: [{ ID: 1, hireDate: 1491821760000, position: "CTO" }, // ... ], columns: [ "ID", { dataField: "hireDate", dataType: "date" }, "position" ], onInitNewRow: function(e) { e.data.hireDate = new Date(); e.promise = getDefaultData().done(function(data) { e.data.ID = data.ID; e.data.position = data.Position; }); } }); function getDefaultData() { var promise = $.ajax({ // The URL returns { ID: 100, Position: "Programmer" } url: "https://www.mywebsite.com/api/getDefaultData", dataType: "json" }); return promise; } })
Angular
<dx-data-grid ... [dataSource]="employees" (onInitNewRow)="onInitNewRow($event)"> <dxi-column dataField="ID"></dxi-column> <dxi-column dataField="hireDate" dataType="date"></dxi-column> <dxi-column dataField="position"></dxi-column> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { employees = [{ ID: 1, hireDate: 1491821760000, position: "CTO" }, // ... ]; onInitNewRow(e) { e.data.hireDate = new Date(); e.promise = this.getDefaultData().then((data: any) => { e.data.ID = data.ID; e.data.position = data.Position; }); } getDefaultData() { return this.httpClient.get("https://www.mywebsite.com/api/getDefaultData") .toPromise() .then(data => { // "data" is { ID: 100, Position: "Programmer" } return data; }) .catch(error => { throw 'Data Loading Error' }); } }
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 { }
Vue
<template> <DxDataGrid ... :data-source="employees" @init-new-row="initNewRow"> <DxColumn data-field="ID" /> <DxColumn data-field="hireDate" data-type="date" /> <DxColumn data-field="position" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid'; import 'whatwg-fetch'; const employees = [{ ID: 1, hireDate: 1491821760000, position: "CTO" }, // ... ]; export default { components: { DxDataGrid, DxColumn }, data() { employees }, methods: { initNewRow(e) { e.data.hireDate = new Date(); e.promise = this.getDefaultData().then(data => { e.data.ID = data.ID; e.data.position = data.Position; }); } getDefaultData() { return fetch("https://www.mywebsite.com/api/getDefaultData") .then(response => response.json()) .then((data) => { // "data" is { ID: 100, Position: "Programmer" } return data; }) .catch(() => { throw 'Data Loading Error' }); } } }; </script>
React
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'; import 'whatwg-fetch'; const employees = [{ ID: 1, hireDate: 1491821760000, position: "CTO" }, // ... ]; class App extends React.Component { constructor(props) { super(props); this.onInitNewRow = this.onInitNewRow.bind(this); this.getDefaultData = this.getDefaultData.bind(this); } onInitNewRow(e) { e.promise = this.getDefaultData().then(data => { e.data.ID = data.ID; e.data.position = data.Position; }); e.data.hireDate = new Date(); } getDefaultData() { return fetch("https://www.mywebsite.com/api/getDefaultData") .then(response => response.json()) .then((data) => { // "data" is { ID: 100, Position: "Programmer" } return data; }) .catch(() => { throw 'Data Loading Error' }); } render() { return ( <DataGrid ... dataSource={employees} onInitNewRow={this.onInitNewRow}> <Column dataField="ID" /> <Column dataField="hireDate" dataType="date" /> <Column dataField="position" /> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() .DataSource(new JS("employees")) .Columns(c => { c.Add().DataField("ID"); c.Add().DataField("hireDate") .DataType(GridColumnDataType.Date); c.Add().DataField("position"); }) .OnInitNewRow("onInitNewRow") ) <script type="text/javascript"> var employees = [{ ID: 1, hireDate: 1491821760000, position: "CTO" }, // ... ]; function onInitNewRow(e) { e.data.hireDate = new Date(); e.promise = getDefaultData().done(data => { e.data.ID = data.ID; e.data.position = data.Position; }); } function getDefaultData() { let promise = $.ajax({ // The URL returns { ID: 100, Position: "Programmer" } url: "https://www.mywebsite.com/api/getDefaultData", dataType: "json", }); return promise; } </script>
onKeyDown
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. This event is based on the keydown native event. |
handled |
Indicates whether the UI component has already handled this event. |
|
jQueryEvent |
Use 'event' instead. The jQuery event that caused the function's execution. Deprecated in favor of the event field. |
|
model |
Model data. Available only if you use Knockout. |
jQuery
$(function() { $("#dataGrid").dxDataGrid({ // ... onKeyDown(e) { if (e.event.ctrlKey && e.event.key === "Q") { console.log("Ctrl + Q was pressed"); } } }); });
Angular
<dx-data-grid ... (onKeyDown)="onKeyDown($event)"> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { onKeyDown(e) { if (e.event.ctrlKey && e.event.key === "Q") { console.log("Ctrl + Q was pressed"); } } }
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 { }
Vue
<template> <DxDataGrid ... @key-down="onKeyDown"> </DxDataGrid> </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 }, methods: { onKeyDown(e) { if (e.event.ctrlKey && e.event.key === "Q") { console.log("Ctrl + Q was pressed"); } } } } </script>
React
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'; class App extends React.Component { render() { return ( <DataGrid ... onKeyDown={this.onKeyDown}> </DataGrid> ); } onKeyDown(e) { if (e.event.ctrlKey && e.event.key === "Q") { console.log("Ctrl + Q was pressed"); } } } export default App;
onOptionChanged
Name | Type | Description |
---|---|---|
model |
Model data. Available only if you use Knockout. |
|
fullName |
The path to the modified property that includes all parent properties. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
component |
The UI component's instance. |
|
name |
The modified property if it belongs to the first level. Otherwise, the first-level property it is nested into. |
|
value | any |
The modified property's new value. |
The following example shows how to subscribe to component property changes:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... onOptionChanged: function(e) { if(e.name === "changedProperty") { // handle the property change here } } }); });
Angular
<dx-data-grid ... (onOptionChanged)="handlePropertyChange($event)"> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { // ... handlePropertyChange(e) { if(e.name === "changedProperty") { // handle the property change here } } }
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 { }
Vue
<template> <DxDataGrid ... @option-changed="handlePropertyChange" /> </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 }, // ... methods: { handlePropertyChange: function(e) { if(e.name === "changedProperty") { // handle the property change here } } } } </script>
React
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'; const handlePropertyChange = (e) => { if(e.name === "changedProperty") { // handle the property change here } } export default function App() { return ( <DataGrid ... onOptionChanged={handlePropertyChange} /> ); }
onRowClick
Name | Type | Description |
---|---|---|
columns |
All column configurations. |
|
component |
The UI component's instance. |
|
data |
The row's data. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
groupIndex |
The row's group index. Available if rowType is "group". |
|
handled |
Indicates whether internal UI component functions have already handled the event. |
|
isExpanded |
Indicates whether or not the group row is expanded. Available if rowType is "group". |
|
isNewRow |
Indicates that the row is added, but not yet saved. Available if rowType is "data". |
|
isSelected |
Indicates whether the row is selected. |
|
jQueryEvent |
Use 'event' instead. The jQuery event that caused the function's execution. Deprecated in favor of the event field. |
|
key | any |
The row's key. |
model |
Model data. Available only if Knockout is used. |
|
rowElement |
The row's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
rowIndex |
The row's index. Refer to Column and Row Indexes for more information. |
|
rowType |
The row's type. |
|
values | Array<any> |
Values displayed in the row cells. |
The UI component executes the onCellClick function and can also execute internal functions before this function. Use the handled field to check whether internal functions were executed.
In the following code, the onRowClick function calls the editRow method to switch the clicked row to the editing state. This functionality is best applied in form or popup editing.mode:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... editing: { mode: "form "}, onRowClick: function(e) { if(e.rowType === "data") { e.component.editRow(e.rowIndex); } } }); });
Angular
<dx-data-grid ... (onRowClick)="startEdit($event)"> <dxo-editing mode="form"></dxo-editing> </dx-data-grid>
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { // ... startEdit(e) { if(e.rowType === "data") { e.component.editRow(e.rowIndex); } } }
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 ], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <DxDataGrid ... @row-click="startEdit"> <DxEditing mode="form" /> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DxDataGrid, { DxEditing } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid }, methods: { startEdit(e) { if(e.rowType === "data") { e.component.editRow(e.rowIndex); } } } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DataGrid, { Editing } from 'devextreme-react/data-grid'; class App extends React.Component { render() { return ( <DataGrid ... onRowClick={this.startEdit}> <Editing mode="form"> </DataGrid> ); } startEdit = (e) => { if(e.rowType === "data") { e.component.editRow(e.rowIndex); } } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... .Editing(e => e.Mode(GridEditMode.Form)) .OnRowClick("startEdit") ) <script type="text/javascript"> function startEdit(e) { if(e.rowType === "data") { e.component.editRow(e.rowIndex); } } </script>
onRowCollapsed
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The key of the row. |
model |
Model data. Available only if you use Knockout. |
onRowCollapsing
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel row collapsing. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The key of the row. |
model |
Model data. Available only if you use Knockout. |
onRowDblClick
A function that is executed when a row is double-clicked or double-tapped. Executed after onCellDblClick.
Name | Type | Description |
---|---|---|
columns |
The configurations of visible columns. |
|
component |
The UI component's instance. |
|
data |
The row's data. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
event | Event (jQuery or EventObject) |
The event that caused the function to execute. It is a dxEvent or a jQuery.Event when you use jQuery. |
groupIndex |
The row's group index. Available if rowType is "group". |
|
isExpanded |
Indicates whether the row is expanded or collapsed. Available if rowType is "data", "detail", or "group". |
|
isNewRow |
Indicates that the row is added, but not yet saved. Available if rowType is "data". |
|
isSelected |
Indicates whether the row is selected. Available if rowType is "data" or "detail". |
|
key | any |
The row's key or a group row's key. Available if the rowType is "data", "detail", "detailAdaptive", or "group". |
model |
Model data. Available only if you use Knockout. |
|
rowElement |
The row's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
rowIndex |
The row's index. Refer to Column and Row Indexes for more information. |
|
rowType |
The row's type. |
|
values | Array<any> |
Raw values displayed in the row's cells. |
onRowDblClick is not executed when the clicked row enters or is in the editing state. You can use onCellDblClick instead.
This event handler is also not executed on mobile devices, because double tap gesture is reserved for zooming. To force onRowDblClick execution, add the following CSS property to the UI component's container:
<div style="touch-action:manipulation"></div>
onRowExpanded
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The key of the row. |
model |
Model data. Available only if you use Knockout. |
onRowExpanding
Name | Type | Description |
---|---|---|
cancel |
Allows you to cancel row expansion. |
|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The key of the group or master row. |
model |
Model data. Available only if you use Knockout. |
onRowInserted
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
data |
The data of the row. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
error |
The standard Error object defining an error that may occur during insertion. |
|
key | any |
The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
onRowInserting
Name | Type | Description |
---|---|---|
cancel | | |
true, a Promise resolved with true, or a rejected Promise stops row insertion. |
component |
The UI component's instance. |
|
data |
The data of the row that should be inserted. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
This function allows you to intercept row insertion and perform additional actions. The following code shows how to use the function parameter's cancel field to prevent or continue row insertion. In this code, a Promise is assigned to this field. Row insertion continues if a user confirms it and row data validation on the server succeeds (the Promise is resolved); otherwise, row insertion is prevented (the Promise is rejected):
jQuery
$(function(){ $("#dataGridContainer").dxDataGrid({ // ... onRowInserting: function(e) { const deferred = $.Deferred(); const promptPromise = DevExpress.ui.dialog.confirm("Are you sure?", "Confirm changes"); promptPromise.done((dialogResult) => { if (dialogResult) { $.ajax({ url: "https://url/to/your/validation/service", dataType: "json", data: e.newData, success: function(validationResult) { if (validationResult.errorText) { deferred.reject(validationResult.errorText); } else { deferred.resolve(false); } }, error: function() { deferred.reject("Data Loading Error"); }, timeout: 5000 }); } else { deferred.resolve(true); } }); e.cancel = deferred.promise(); } }) })
Angular
import { HttpClient, HttpClientModule, HttpParams } from "@angular/common/http"; import { confirm } from 'devextreme/ui/dialog'; // ... export class AppComponent { constructor(private httpClient: HttpClient) { /*...*/} // ... async insertRow(e) { const isCanceled = async () => { const dialogResult = await confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = new HttpParams(); for (let key in e.newData) { params = params.set(key, e.newData[key]); } const validationResult = await this.httpClient .get("https://url/to/your/validation/service", { params: params }) .toPromise(); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } }
<dx-data-grid ... (onRowInserting)="insertRow($event)"> </dx-data-grid>
// ... import { DxDataGridModule } from 'devextreme-angular'; import { HttpClientModule } from "@angular/common/http"; @NgModule({ imports: [ // ... DxDataGridModule, HttpClientModule ], // ... })
Vue
<template> <DxDataGrid ... @row-inserting="insertRow"> </DxDataGrid> </template> <script> import DxDataGrid, { ... } from 'devextreme-vue/data-grid'; import dialog from 'devextreme/ui/dialog'; // ... export default { components: { DxDataGrid, // ... }, // ... methods: { async insertRow(e) { const isCanceled = async () => { const dialogResult = await dialog.confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = "?"; for (let key in e.newData) { params += `${key}=${e.newData[key]}&`; } params = params.slice(0, -1); const validationResult = await fetch(`https://url/to/your/validation/service${params}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } }, }; </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import dialog from 'devextreme/ui/dialog'; import DataGrid, { ... } from 'devextreme-react/data-grid'; async function insertRow(e) { const isCanceled = async () => { const dialogResult = await dialog.confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = "?"; for (let key in e.newData) { params += `${key}=${e.newData[key]}&`; } params = params.slice(0, -1); const validationResult = await fetch(`https://url/to/your/validation/service${params}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } function App() { return ( <DataGrid ... onRowInserting={insertRow}> // ... </DataGrid> ); } export default App;
Do not use this function to insert data. If you need a custom insert logic, implement CustomStore's insert function.
In batch editing mode, this function is executed for each row individually if several rows should be inserted.
onRowPrepared
Name | Type | Description |
---|---|---|
columns |
All column configurations. |
|
component |
The UI component's instance. |
|
data |
The row's raw data. Unavailable if rowType is "header", "filter", or "totalFooter". |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
groupIndex |
The row's group index. Available if rowType is "group". |
|
isExpanded |
Indicates whether the row is expanded or collapsed. Unavailable if rowType is "header", "filter", or "totalFooter". |
|
isNewRow |
Indicates that the row is added, but not yet saved. Available if rowType is "data". |
|
isSelected |
Indicates whether the prepared row is selected. Available only if rowType is "data". |
|
key | any |
The row's key. |
model |
Model data. Available only if Knockout is used. |
|
rowElement |
The row's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
rowIndex |
The row's index. Refer to Column and Row Indexes for more information. |
|
rowType |
The row's type. |
|
values | Array<any> |
Values displayed in the row cells. |
onRowRemoved
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
data |
The data of the row. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
error |
The standard Error object defining an error that may occur during removal. |
|
key | any |
The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
onRowRemoving
Name | Type | Description |
---|---|---|
cancel | | |
true, a Promise resolved with true, or a rejected Promise stops row removal. |
component |
The UI component's instance. |
|
data |
The data of the row that should be removed. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The row's key. |
model |
Model data. Available only if you use Knockout. |
This function allows you to intercept row removal and perform additional actions. The following code shows how to use the function parameter's cancel field to prevent or continue removal. In this code, a Promise is assigned to this field. Removal continues if a user confirms it and row validation on the server succeeds (the Promise is resolved); otherwise, removal is prevented (the Promise is rejected):
jQuery
$(function(){ $("#dataGridContainer").dxDataGrid({ // ... onRowRemoving: function(e) { var deferred = $.Deferred(); $.ajax({ url: `https://url/to/your/validation/service/${e.key}`, success: function(validationResult) { if (validationResult.errorText) { deferred.reject(validationResult.errorText); } else { deferred.resolve(false); } }, error: function() { deferred.reject("Data Loading Error"); }, timeout: 5000 }); e.cancel = deferred.promise(); }, }) })
Angular
import { DxDataGridModule } from "devextreme-angular"; import { HttpClient, HttpClientModule, HttpParams } from "@angular/common/http"; // ... export class AppComponent { constructor(private httpClient: HttpClient) { /*...*/} async validateRemove(e) { const isCanceled = async () => { const validationResult = await this.httpClient .get(`https://url/to/your/validation/service/${e.key}`) .toPromise(); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } e.cancel = await isCanceled(); } }
<dx-data-grid ... (onRowRemoving)="validateRemove($event)"> </dx-data-grid>
// ... import { DxDataGridModule } from 'devextreme-angular'; import { HttpClientModule } from "@angular/common/http"; @NgModule({ imports: [ // ... DxDataGridModule, HttpClientModule ], // ... })
Vue
<template> <DxDataGrid ... @row-removing="validateRemove"> </DxDataGrid> </template> <script> import DxDataGrid, { ... } from 'devextreme-vue/data-grid'; import dialog from 'devextreme/ui/dialog'; // ... export default { components: { DxDataGrid, // ... }, // ... methods: { async validateRemove(e) { const isCanceled = async () => { const validationResult = await fetch(`https://url/to/your/validation/service/${e.key}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } }; e.cancel = await isCanceled(); } }, }; </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import dialog from 'devextreme/ui/dialog'; import DataGrid, { ... } from 'devextreme-react/data-grid'; async function validateRemove(e) { const isCanceled = async () => { const validationResult = await fetch(`https://url/to/your/validation/service/${e.key}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } }; e.cancel = await isCanceled(); } function App() { return ( <DataGrid ... onRowRemoving={validateRemove}> // ... </DataGrid> ); } export default App;
onRowUpdated
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
data |
The updated data of the row. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
error |
The standard Error object defining an error that may occur during updating. |
|
key | any |
The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
onRowUpdating
Name | Type | Description |
---|---|---|
cancel | | |
true, a Promise resolved with true, or a rejected Promise stops row updating. |
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
key | any |
The row's key. |
model |
Model data. Available only if you use Knockout. |
|
newData |
The row's updated data. |
|
oldData |
The row's old data. |
This function allows you to intercept row update and perform additional actions. The following code shows how to use the function parameter's cancel field to prevent or continue row update. In this code, a Promise is assigned to this field. Row update continues if a user confirms it and row data validation on the server succeeds (the Promise is resolved); otherwise, row update is prevented (the Promise is rejected).
jQuery
$(function(){ $("#dataGridContainer").dxDataGrid({ // ... onRowUpdating: function(e) { const deferred = $.Deferred(); const promptPromise = DevExpress.ui.dialog.confirm("Are you sure?", "Confirm changes"); promptPromise.done((dialogResult) => { if (dialogResult) { $.ajax({ url: "https://url/to/your/validation/service", dataType: "json", data: e.newData, success: function(validationResult) { if (validationResult.errorText) { deferred.reject(validationResult.errorText); } else { deferred.resolve(false); } }, error: function() { deferred.reject("Data Loading Error"); }, timeout: 5000 }); } else { deferred.resolve(true); } }); e.cancel = deferred.promise(); } }) })
Angular
import { HttpClient, HttpClientModule, HttpParams } from "@angular/common/http"; import { confirm } from 'devextreme/ui/dialog'; // ... export class AppComponent { constructor(private httpClient: HttpClient) { /*...*/} // ... async updateRow(e) { const isCanceled = async () => { const dialogResult = await confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = new HttpParams(); for (let key in e.newData) { params = params.set(key, e.newData[key]); } const validationResult = await this.httpClient .get("https://url/to/your/validation/service", { params: params }) .toPromise(); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } }
<dx-data-grid ... (onRowUpdating)="updateRow($event)"> </dx-data-grid>
// ... import { DxDataGridModule } from 'devextreme-angular'; import { HttpClientModule } from "@angular/common/http"; @NgModule({ imports: [ // ... DxDataGridModule, HttpClientModule ], // ... })
Vue
<template> <DxDataGrid ... @row-updating="updateRow"> </DxDataGrid> </template> <script> import DxDataGrid, { ... } from 'devextreme-vue/data-grid'; import dialog from 'devextreme/ui/dialog'; // ... export default { components: { DxDataGrid, // ... }, // ... methods: { async updateRow(e) { const isCanceled = async () => { const dialogResult = await dialog.confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = "?"; for (let key in e.newData) { params += `${key}=${e.newData[key]}&`; } params = params.slice(0, -1); const validationResult = await fetch(`https://url/to/your/validation/service${params}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } }, }; </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import dialog from 'devextreme/ui/dialog'; import DataGrid, { ... } from 'devextreme-react/data-grid'; async function updateRow(e) { const isCanceled = async () => { const dialogResult = await dialog.confirm("Are you sure?", "Confirm changes"); if (dialogResult) { let params = "?"; for (let key in e.newData) { params += `${key}=${e.newData[key]}&`; } params = params.slice(0, -1); const validationResult = await fetch(`https://url/to/your/validation/service${params}`); if (validationResult.errorText) { console.log(validationResult.errorText); return true; } else { return false; } } else { return true; } } e.cancel = await isCanceled(); } function App() { return ( <DataGrid ... onRowUpdating={updateRow}> // ... </DataGrid> ); } export default App;
Do not use this function to update data. If you need a custom update logic, implement CustomStore's update function.
In batch editing mode, this function is executed for each row individually if several rows should be updated.
onRowValidating
A function that is executed after cells in a row are validated against validation rules.
Name | Type | Description |
---|---|---|
brokenRules | Array<RequiredRule | NumericRule | RangeRule | StringLengthRule | CustomRule | CompareRule | PatternRule | EmailRule | AsyncRule> |
An array of broken rules. The structure of rule objects is described in the Validation Rules section. |
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
errorText |
An error message to be displayed. |
|
isValid |
Indicates whether data in all row cells satisfies the validation rules. |
|
key | any |
The key of the row. If a field providing keys is not specified in the data source, the whole data object is considered the key. |
model |
Model data. Available only if you use Knockout. |
|
newData |
The data of the validated row after changes. |
|
oldData |
The data of the validated row before changes. |
|
promise |
Assign a Promise to this field to perform an asynchronous operation, such as a request to a server. |
Use this function to perform operations before messages about failed validation are shown. For instance, you can run additional checks and change the isValid function parameter to change the validation result. You can also change the errorText parameter to correct the error message.
The following code illustrates how to validate an email address on the server and display an error row with a custom error text if the validation fails:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... onRowValidating: function(e) { if(e.newData.Email) { e.promise = checkEmail(e.newData.Email) .done(function(result) { e.errorText = result.errorText; e.isValid = result.isValid; }); } } }); }); function checkEmail(email) { return $.ajax({ // The url returns { errorText: "The Email address you entered already exists.", isValid: false } url: "https://www.mywebsite.com/api/checkEmail", dataType: "json", data: { email: email } }); }
Angular
<dx-data-grid ... (onRowValidating)="onRowValidating($event)"> </dx-data-grid>
import { Component } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(@Inject(HttpClient) http: HttpClient) { this.checkEmail = this.checkEmail.bind(this); } onRowValidating(e) { if(e.newData.Email) { e.promise = this.checkEmail(e.newData.Email) .then((result: any) => { // "result" is { errorText: "The Email address you entered already exists.", isValid: false } e.errorText = result.errorText; e.isValid = result.isValid; }); } } checkEmail(email) { const params = new HttpParams().set("email", email); return this.http.get("https://www.mywebsite.com/api/checkEmail", { params }) .toPromise(); } }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule, Component } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { DxDataGridModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule, DxDataGridModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Vue
<template> <DxDataGrid ... @row-validating="onRowValidating"> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import DxDataGrid from 'devextreme-vue/data-grid'; import 'whatwg-fetch'; export default { components: { DxDataGrid }, // ... methods: { onRowValidating(e) { if(e.newData.Email) { e.promise = this.checkEmail(e.newData.Email) .then((result: any) => { // "result" is { errorText: "The Email address you entered already exists.", isValid: false } e.errorText = result.errorText; e.isValid = result.isValid; }); } }, checkEmail(email) { let params = '?' + 'email=' + email; return fetch("https://www.mywebsite.com/api/checkEmail${params}") .toPromise(); } } } </script>
React
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 'whatwg-fetch'; class App extends React.Component { constructor(props) { super(props); this.onRowValidating = this.onRowValidating.bind(this); } onRowValidating(e) { if(e.newData.Email) { e.promise = this.checkEmail(e.newData.Email) .then((result: any) => { // "result" is { errorText: "The Email address you entered already exists.", isValid: false } e.errorText = result.errorText; e.isValid = result.isValid; }); } } checkEmail(email) { let params = '?' + 'email=' + email; return fetch("https://www.mywebsite.com/api/checkEmail${params}") .toPromise(); } render() { return ( <DataGrid ... onRowValidating={this.onRowValidating}> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... .OnRowValidating("onRowValidating") ) <script type="text/javascript"> function onRowValidating(e) { if(e.newData.Email) { e.promise = checkEmail(e.newData.Email) .done(function(result) { e.errorText = result.errorText; e.isValid = result.isValid; }); } } function checkEmail(email) { return $.ajax({ // The url returns { errorText: "The Email address you entered already exists.", isValid: false } url: "https://www.mywebsite.com/api/checkEmail", dataType: "json", data: { email: email } }); } </script>
onSelectionChanged
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
currentDeselectedRowKeys | Array<any> |
The keys of the rows whose selection has been cleared. |
currentSelectedRowKeys | Array<any> |
The keys of the rows that have been selected. |
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
selectedRowKeys | Array<any> |
The keys of all selected rows. |
selectedRowsData |
The data of all selected rows. |
This function has the following specifics:
- If a field providing key values is not specified in the data source, the whole data object is considered the key. In this case, all arrays passed to the function contain data objects instead of keys.
- When selection is deferred, this function does not provide access to keys and data. Use the getSelectedRowsData() or getSelectedRowKeys() method instead.
onToolbarPreparing
Name | Type | Description |
---|---|---|
component |
The UI component's instance. |
|
element |
The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery. |
|
model |
Model data. Available only if you use Knockout. |
|
toolbarOptions |
This function allows you to customize the toolbar. Depending on the configuration, the UI component may add the following items to the toolbar:
- - "columnChooserButton"
- - "addRowButton"
- - "saveButton"
- - "revertButton"
- - "exportButton"
- - "applyFilterButton"
- "groupPanel"
- "searchPanel"
The following code shows how to use this function to customize the toolbar:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... onToolbarPreparing: function (e) { let toolbarItems = e.toolbarOptions.items; // Modifies an existing item toolbarItems.forEach(function(item) { if (item.name === "saveButton") { item.options = { icon: "custom-save-icon", onClick: function(e) { // Implement custom save logic here } } } }); // Adds a new item toolbarItems.push({ widget: "dxButton", options: { icon: "user", onClick: function() { ... } }, location: "after" }); } }); });
Angular
import { DxDataGridModule, DxButtonModule } from "devextreme-angular"; // ... export class AppComponent { onToolbarPreparing (e) { let toolbarItems = e.toolbarOptions.items; // Modifies an existing item toolbarItems.forEach(function(item) { if (item.name === "saveButton") { item.options = { icon: "custom-save-icon", onClick: function(e) { // Implement custom save logic here } } } }); // Adds a new item toolbarItems.push({ widget: "dxButton", options: { icon: "user", onClick: function () { ... } }, location: "after" }); } } @NgModule({ imports: [ // ... DxDataGridModule, DxButtonModule ], // ... })
<dx-data-grid ... (onToolbarPreparing)="onToolbarPreparing($event)"> </dx-data-grid>
Vue
<template> <DxDataGrid ... @toolbar-preparing="onToolbarPreparing" /> </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 }, methods: { onToolbarPreparing(e) { let toolbarItems = e.toolbarOptions.items; // Modifies an existing item toolbarItems.forEach(function(item) { if (item.name === "saveButton") { item.options = { icon: "custom-save-icon", onClick: function(e) { // Implement custom save logic here } } } }); // Adds a new item toolbarItems.push({ widget: 'dxButton', options: { icon: 'user', onClick: function() { // ... } }, location: 'after' }); } } } </script>
React
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'; class App extends React.Component { render() { return ( <DataGrid ... onToolbarPreparing={this.onToolbarPreparing} /> ); } onToolbarPreparing(e) { let toolbarItems = e.toolbarOptions.items; // Modifies an existing item toolbarItems.forEach(function(item) { if (item.name === "saveButton") { item.options = { icon: "custom-save-icon", onClick: function(e) { // Implement custom save logic here } } } }); // Adds a new item toolbarItems.push({ widget: 'dxButton', options: { icon: 'user', onClick: function() { // ... } }, location: 'after' }); } } export default App;
pager
The pager is an element that allows users to navigate through pages and change their size at runtime. The pager consists of the page navigator and several optional elements: the page size selector, navigation buttons, and page information.
See Also
paging
Paging allows the UI component to load data in portions instead of loading it simultaneously. To enable paging, set the paging.enabled property to true.
Users can switch between pages and change paging settings using the pager or they can scroll the pages. Paging settings apply with any scrolling mode.
See Also
remoteOperations
Server-side data processing improves the UI component's performance on large datasets. When the server does not implement particular operations (and/or the corresponding remoteOperations fields are false) they are executed on the client. Note that the UI component may send queries to the server while executing a client-side operation.
The following table lists the possible remoteOperations configurations and the operations the server should implement. The server should also implement additional operations depending on the used UI component functionality.
Setting | Required server-side operations | Additional server-side operations |
---|---|---|
remoteOperations: true |
all operations except group paging | - |
remoteOperations: { groupPaging: true } |
all operations including group paging | - |
remoteOperations: { paging: true } |
paging | filtering1, sorting1, summary calculation1 |
remoteOperations: { paging: true } (with grouping used in the UI component) |
paging, filtering, sorting | grouping3, summary calculation1 |
remoteOperations: { filtering: true } |
filtering | - |
remoteOperations: { sorting: true } |
sorting | filtering1 |
remoteOperations: { grouping: true } |
grouping, filtering | sorting1, summary calculation1 |
remoteOperations: { summary: true } |
summary calculation | filtering1, sorting2, grouping2 |
- If this functionality is used in the UI component.
- If group summary calculation is used.
- If grouping.autoExpandAll is set to false.
The following restrictions apply to UI component functionality when operations are remote:
Columns with the calculateCellValue or calculateDisplayValue property set cannot be sorted, filtered, or used for grouping.
The calculateGroupValue and calculateSortValue properties accept only string values.
Custom summary calculation is not supported.
The calculateFilterExpression property does not apply if it returns a function or a filter expression that contains functions.
Web API Service Demo Custom Service Demo
See Also
- Data Binding: Web API, PHP, MongoDB | Custom Sources
renderAsync
Specifies whether to render the filter row, command columns, and columns with showEditorAlways set to true after other elements.
repaintChangesOnly
See Also
- push(changes) in: ArrayStore | CustomStore | LocalStore | ODataStore
- DataSource.reshapeOnPush
rowAlternationEnabled
All rows are monochrome without any visual distinctions by default. However, if you set this property to true, ordinary-looking rows will alternate with slightly shaded ones.
rowComponent
An alias for the rowTemplate property specified in React. Accepts a custom component. Refer to Using a Custom Component for more information.
rowRender
An alias for the rowTemplate property specified in React. Accepts a rendering function. Refer to Using a Rendering Function for more information.
rowTemplate
The following details should be taken into account when you use a rowTemplate:
Disable column reordering, grouping, and column fixing when you specify the row template. Its content cannot automatically synchronize with the column layout, which makes these features inoperative. Command columns are not supported either.
You should implement the following features manually: editing, adaptability, multiple selection, and master-detail interface. Follow the links to see the API that can help you with this task.
When the DataGrid is exported, it omits customizations made in the template. However, you can recreate them in the exported file using the ExcelJS API. Use the customizeCell function to do this.
In AngularJS and Knockout, use the dxTemplate and declare it within a <table>
element. In other cases, declare the markup in a <tbody>
element with the dx-row
class.
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... rowTemplate: function(container, item) { var data = item.data, markup = "<tbody class='dx-row'>" + "<tr>" + "<td>" + item.data.id + "</td>" + "<td>" + item.data.name + "</td>" + "</tr>" + "</tbody>"; container.append(markup); } }); });
Angular
<dx-data-grid ... rowTemplate="rowTemplateName"> <tbody class="dx-row" *dxTemplate="let item of 'rowTemplateName'" > <tr> <td>{{item.data.id}}</td> <td>{{item.data.name}}</td> </tr> </tbody> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
AngularJS
<div dx-data-grid="{ ... rowTemplate: 'rowTemplateName' }" dx-item-alias="item"> <table data-options="dxTemplate: { name: 'rowTemplateName' }" > <tr> <td>{{item.data.id}}</td> <td>{{item.data.name}}</td> </tr> </table> </div>
Knockout
<div data-bind="dxDataGrid: { ... rowTemplate: 'rowTemplateName' }"> <table data-options="dxTemplate: { name: 'rowTemplateName' }" > <tr> <td data-bind="text: data.id"></td> <td data-bind="text: data.name"></td> </tr> </table> </div>
Vue
<template> <DxDataGrid ... row-template="dataRowTemplate"> <tbody slot="dataRowTemplate" slot-scope="{ data: { data: { id, name } } }" class="dx-row"> <tr> <td>{{id}}</td> <td>{{name}}</td> </tr> </tbody> </DxDataGrid> </template> <script> import { DxDataGrid } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid } }; </script>
React
import React from 'react'; import DataGrid from 'devextreme-react/data-grid'; class Row extends React.PureComponent { render() { const {�data:�{�id,�name�}�} = this.props.data; return ( <tbody className={"dx-row"}> <tr> <td>{id}</td> <td>{name}</td> </tr> </tbody> ); } } class App extends React.Component { render() { return ( <DataGrid ... rowComponent={Row}> </DataGrid> ); } } export default App;
ASP.NET MVC Controls
@(Html.DevExtreme().DataGrid() // ... .RowTemplate(@<text> <tbody class="dx-row"> <tr> <td><%= data.id %></td> <td><%= data.name %></td> </tr> </tbody> </text>) )
You can also use a 3rd-party template engine to customize row appearance. See the 3rd-Party Template Engines article for more information. Note that the <tbody>
element that represents a row should have the dx-row
class to ensure all UI component features work properly.
See Also
rtlEnabled
When this property is set to true, the UI component text flows from right to left, and the layout of elements is reversed. To switch the entire application/site to the right-to-left representation, assign true to the rtlEnabled field of the object passed to the DevExpress.config(config) method.
DevExpress.config({ rtlEnabled: true });
See Also
- Right-to-Left Support Demo: DataGrid | Navigation Widgets | Editors
searchPanel
The search panel allows searching for values in several columns at once. The UI component searches against only those columns whose allowSearch property is set to true.
To make the search panel visible, set the searchPanel.visible property to true.
See Also
selectedRowKeys
Allows you to select rows or determine which rows are selected. Applies only if selection.deferred is false.
Array<any>
Keys are stored in the order the user selects rows.
To access a row using its key, specify the data field that provides key values. Assign the data field's name to the key property of the store that underlies the dataSource.
See Also
selection
A user can select rows in a single or multiple mode. In multiple mode, a user can select all rows at once. To disable this feature, assign false to the allowSelectAll.
By default, once a user selects a row, the data source is instantly notified about it. This may lower the UI component performance if the data source is remote and the user is allowed to select all rows at once. In this case, we recommend making the selection deferred.
See Also
selectionFilter
Specifies filters for the rows that must be selected initially. Applies only if selection.deferred is true.
This property also allows you to obtain filter expressions for the currently selected rows. Note that if all records are selected, the selectionFilter value is null. If there are no selected records, the value contains an empty array.
See Also
showColumnLines
See Also
sortByGroupSummaryInfo[]
Allows you to sort groups according to the values of group summary items.
Normally, when records are grouped by a column, the groups are sorted according to the values of this column. In a number of cases, such approaches cannot address your needs, e.g., when you require to sort groups by the number of records in each. For these cases, you can implement sorting according to the values of group summary items. These items are specified in the groupItems array. Assume that you have the following code that specifies three group summary items.
jQuery
$(function () { $("#dataGridContainer").dxDataGrid({ // ... summary: { groupItems: [{ column: "Age", summaryType: "avg", name: "Average Age Group Summary" }, { column: "Income", summaryType: "max" }, { column: "Tasks", summaryType: "min" }] } }); });
Angular
<dx-data-grid ... > <dxo-summary> <dxi-group-item column="Age" summaryType="avg" name="Average Age Group Summary"> </dxi-group-item> <dxi-group-item column="Income" summaryType="max"> </dxi-group-item> <dxi-group-item column="Tasks" summaryType="min"> </dxi-group-item> </dxo-summary> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid> <DxSummary> <DxGroupItem column="Age" summary-type="avg" name="Average Age Group Summary" /> <DxGroupItem column="Income" summary-type="max" /> <DxGroupItem column="Tasks" summary-type="min" /> </DxSummary> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxSummary, DxGroupItem } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxSummary, DxGroupItem } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DataGrid, Summary, GroupItem } from 'devextreme-react/data-grid'; class App extends React.Component { render() { return ( <DataGrid> <Summary> <GroupItem column="Age" summaryType="avg" name="Average Age Group Summary" /> <GroupItem column="Income" summaryType="max" /> <GroupItem column="Tasks" summaryType="min" /> </Summary> </DataGrid> ); } } export default App;
To use these summary items for sorting groups, assign an array of objects to the sortByGroupSummaryInfo property. In each object of this array, specify the summaryItem field. This field determines the summary item to be used for summary-based sorting. In the following code, three objects form the sortByGroupSummaryInfo array. In each object, the summaryItem property determines different summary items using different values.
jQuery
$(function () { $("#dataGridContainer").dxDataGrid({ // ... sortByGroupSummaryInfo: [ { summaryItem: 1 }, // determines the maximum income item using its index in the "groupItems" array { summaryItem: "min" }, // determines the minimum tasks item using its aggregate function { summaryItem: "Average Age Group Summary" } // determines the average age item using its name ] }); });
Angular
<dx-data-grid ... > <dxi-sort-by-group-summary-info [summaryItem]="1"> <!-- determines the maximum income item using its index in the "groupItems" array --> </dxi-sort-by-group-summary-info> <dxi-sort-by-group-summary-info summaryItem="min"> <!-- determines the minimum tasks item using its aggregate function --> </dxi-sort-by-group-summary-info> <dxi-sort-by-group-summary-info summaryItem="Average Age Group Summary"> <!-- determines the average age item using its name --> </dxi-sort-by-group-summary-info> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid> <DxSortByGroupSummaryInfo :summary-item="1"/> <!-- determines the maximum income item using its index in the "groupItems" array --> <DxSortByGroupSummaryInfo summary-item="min"/> <!-- determines the minimum tasks item using its aggregate function --> <DxSortByGroupSummaryInfo summary-item="Average Age Group Summary"/> <!-- determines the average age item using its name --> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxSortByGroupSummaryInfo } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxSortByGroupSummaryInfo } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DataGrid, SortByGroupSummaryInfo } from 'devextreme-react/data-grid'; class App extends React.Component { render() { return ( <DataGrid> <SortByGroupSummaryInfo summaryItem={1}/> {/* determines the maximum income item using its index in the "groupItems" array */} <SortByGroupSummaryInfo summaryItem="min"/> {/* determines the minimum tasks item using its aggregate function */} <SortByGroupSummaryInfo summaryItem="Average Age Group Summary"/> {/* determines the average age item using its name */} </DataGrid> ); } } export default App;
After that, set the groupColumn property for objects in the sortByGroupSummaryInfo array. This property identifies the column that must be used in grouping in order that a particular summary-based sorting setting be applied. If you have omitted this property from an object, the sorting setting specified by this object will be applied regardless of the column used in grouping.
jQuery
$(function () { $("#gridContainer").dxDataGrid({ // ... sortByGroupSummaryInfo: [ { summaryItem: 1, groupColumn: "Tasks" }, // applies sorting only when records are grouped by the "Tasks" column { summaryItem: "min", groupColumn: "Last Name" }, // applies sorting only when records are grouped by a "Last Name" column { summaryItem: "Average Age Group Summary" } // applies sorting regardless the grouping column ] }); });
Angular
<dx-data-grid ... > <dxi-sort-by-group-summary-info [summaryItem]="1" groupColumn="Tasks"> <!-- applies sorting only when records are grouped by the "Tasks" column --> </dxi-sort-by-group-summary-info> <dxi-sort-by-group-summary-info summaryItem="min" groupColumn="Last Name"> <!-- applies sorting only when records are grouped by a "Last Name" column --> </dxi-sort-by-group-summary-info> <dxi-sort-by-group-summary-info summaryItem="Average Age Group Summary"> <!-- applies sorting regardless the grouping column --> </dxi-sort-by-group-summary-info> </dx-data-grid>
import { DxDataGridModule } from "devextreme-angular"; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
Vue
<template> <DxDataGrid> <DxSortByGroupSummaryInfo :summary-item="1" group-column="Tasks" /> <!-- applies sorting only when records are grouped by the "Tasks" column --> <DxSortByGroupSummaryInfo summary-item="min" group-column="Last Name" /> <!-- applies sorting only when records are grouped by a "Last Name" column --> <DxSortByGroupSummaryInfo summary-item="Average Age Group Summary" /> <!-- applies sorting regardless the grouping column --> </DxDataGrid> </template> <script> import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DxDataGrid, DxSortByGroupSummaryInfo } from 'devextreme-vue/data-grid'; export default { components: { DxDataGrid, DxSortByGroupSummaryInfo } } </script>
React
import React from 'react'; import 'devextreme/dist/css/dx.common.css'; import 'devextreme/dist/css/dx.light.css'; import { DataGrid, SortByGroupSummaryInfo } from 'devextreme-react/data-grid'; class App extends React.Component { render() { return ( <DataGrid> <SortByGroupSummaryInfo summaryItem={1} groupColumn="Tasks" /> {/* applies sorting only when records are grouped by the "Tasks" column */} <SortByGroupSummaryInfo summaryItem="min" groupColumn="Last Name" /> {/* applies sorting only when records are grouped by a "Last Name" column */} <SortByGroupSummaryInfo summaryItem="Average Age Group Summary" /> {/* applies sorting regardless the grouping column */} </DataGrid> ); } } export default App;
If several summary-based sorting settings match the current grouping, their indexes in the sortByGroupSummaryInfo array will dictate the order of their application.
In addition, you can set an ascending or descending sort order for each summary-based sorting object using its sortOrder property.
See Also
stateStoring
State storing enables the UI component to save applied settings and restore them the next time the UI component is loaded. Assign true to the stateStoring.enabled property to enable this functionality.
State storing saves the following properties:
|
|
|
See Also
summary
A summary is a grid feature that provides a synopsis of data contained in the grid. A summary consists of several items. A summary item displays a value that is a product of applying an aggregate function to the data of a specific column.
There are two types of summary in DataGrid: group and total. The group summary is calculated on a group of data, which is segregated during grouping. To specify the items of the group summary, declare an array of objects and assign it to the summary.groupItems field.
The total summary is calculated on all data contained in the grid. To specify the items of the total summary, declare an array of objects and assign it to the summary.totalItems field.
tabIndex
The value of this property will be passed to the tabindex
attribute of the HTML element that underlies the UI component.
twoWayBindingEnabled
Two-way data binding ensures that the UI tracks changes made in the data source by a 3rd-party component, and vice versa. This way, the UI component and its data source stay synchronized. If you implement two-way data binding in the UI component on your own using the cellTemplate and/or editCellTemplate properties, make sure to set the twoWayBindingEnabled property to false.
width
This property accepts a value of one of the following types:
Number
The width in pixels.String
A CSS-accepted measurement of width. For example,"55px"
,"80%"
,"auto"
,"inherit"
.Function
A function returning either of the above. For example:JavaScriptwidth: function() { return window.innerWidth / 1.5; }
If you have technical questions, please create a support ticket in the DevExpress Support Center.