A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxDataGrid/Configuration/ below:

Vue DataGrid Props | Vue Documentation

This section describes the configuration properties of the DataGrid UI component.

Specifies the shortcut key that sets focus on the UI component.

Selector: access-key

Default Value: undefined

The value of this property will be passed to the accesskey attribute of the HTML element that underlies the UI component.

Specifies whether the UI component changes its visual state as a result of user interaction.

Selector: active-state-enabled

Default Value: false

The UI component switches to the active state when users press down the primary mouse button. When this property is set to true, the CSS rules for the active state apply. You can change these rules to customize the component.

Use this property when you display the component on a platform whose guidelines include the active state change for UI components.

Specifies whether a user can reorder columns.

Selector: allow-column-reordering

Default Value: false

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.

DataGrid Demo TreeList Demo

See Also

Specifies whether a user can resize columns.

Selector: allow-column-resizing

Default Value: false

Automatically scrolls the component to the focused row when the focusedRowKey is changed. Incompatible with infinite scrolling mode.

Selector: auto-navigate-to-focused-row

Default Value: true

You must specify the component's

height

to ensure that the

autoNavigateToFocusedRow

property works properly.

If you set the remoteOperations property to true, the DataGrid generates additional requests with comparison operators (for example, < and >). This logic does not work if ODataStore is bound to a table with GUID keys. You need to disable the autoNavigateToFocusedRow or remoteOperations properties to ensure it operates correctly.

View Demo

Specifies whether data should be cached.

Selector: cache-enabled

Default Value: true

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 reload() method of the DataSource:

jQuery
$("#dataGridContainer").dxDataGrid("refresh");
// ===== or =====
const dataGridDataSource = $("#dataGridContainer").dxDataGrid("getDataSource");
dataGridDataSource.reload();
Angular
import { ..., ViewChild } from "@angular/core";
import { DxDataGridModule, DxDataGridComponent } from "devextreme-angular";
// ...
export class AppComponent {
    @ViewChild(DxDataGridComponent, { static: false }) dataGrid: DxDataGridComponent;
    // Prior to Angular 8
    // @ViewChild(DxDataGridComponent) dataGrid: DxDataGridComponent;
    refreshData () {
        this.dataGrid.instance.refresh();
        // ===== or =====
        const dataGridDataSource = this.dataGrid.instance.getDataSource();
        dataGridDataSource.reload();
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
Vue
<template>
    <DxDataGrid :ref="dataGridRefKey">
        <!-- ... -->
    </DxDataGrid>
</template>

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

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

const dataGridRefKey = "my-data-grid";

export default {
    components: {
        DxDataGrid
    },
    data() {
        return {
            dataGridRefKey
        }
    },
    methods: {
        refreshData() {
            this.dataGrid.refresh();
            // ===== or =====
            const dataGridDataSource = this.dataGrid.getDataSource();
            dataGridDataSource.reload();
        }
    },
    computed: {
        dataGrid: function() {
            return this.$refs[dataGridRefKey].instance;
        }
    }
}
</script>
React
import React from 'react';

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

import DataGrid from 'devextreme-react/data-grid';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.dataGridRef = React.createRef();

        this.refreshData = () => {
            this.dataGrid.refresh();
            // ===== or =====
            const dataGridDataSource = this.dataGrid.getDataSource();
            dataGridDataSource.reload();
        }
    }

    get dataGrid() {
        return this.dataGridRef.current.instance();
    }

    render() {
        return (
            <DataGrid ref={this.dataGridRef}>
                {/* ... */ }
            </DataGrid>
        );
    }
}
export default App;

If you fetch data from the server, some operations with data can be executed

remotely

, while others - locally. If you perform basic operations (sorting, filtering, and paging) remotely and advanced operations (grouping and summary calculation) locally, certain user actions will force the DataGrid to query the server for data repeatedly despite caching being enabled. Particularly, the advanced operations demand data to be reloaded completely from the server to provide correct results.

See Also

Enables a hint that appears when a user hovers the mouse pointer over a cell with truncated content.

Selector: cell-hint-enabled

Default Value: true

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.

Specifies whether columns should adjust their widths to the content.

Selector: column-auto-width

Default Value: false

When this property is set to true, all columns adjust their width to the content.

If the DataGrid is wider than its overall content, the columns are stretched to occupy all available width. To avoid this, set the columnWidth or 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.

DataGrid Demo TreeList Demo

See Also

Configures the column chooser.

Selector: DxColumnChooser

Configures column fixing.

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.

DataGrid Demo TreeList Demo

See Also

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".

Selector: column-hiding-enabled

Default Value: false

Specifies the minimum width of columns.

Selector: column-min-width

Default Value: undefined

Specifies how the UI component resizes columns. Applies only if allowColumnResizing is true.

Selector: column-resizing-mode

Default Value: 'nextColumn'

The columnResizingMode property accepts one of the following values:

DataGrid Demo TreeList Demo

If this property is set to

'nextColumn'

(default) and you enable the

columnHidingEnabled

property, then also enable

columnAutoWidth

to ensure the component works properly.

An array of grid columns.

Selector: DxColumn

Default Value: undefined

Specifies the width for all data columns. Has a lower priority than the column.width property.

Selector: column-width

Default Value: undefined

Customizes columns after they are created.

Selector: customize-columns

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.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.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>

Data operations (sorting, filtering, summary) are unavailable for the columns created via

customizeColumns

. To create a fully functioning column, add it to the

columns

array.

React

Note that the [elementName]Render and [elementName]Component (for example, the cellRender and cellComponent) do not work within the customizeColumn function. Instead, use the columns array.

import React from 'react';

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

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

class App extends React.Component {
    customizeColumns = (columns) => {
        // ...
        // This code does not work
        // columns[0].cellRender = cellRender;
    }

    render() {
        return (
            <DataGrid ...
                customizeColumns={this.customizeColumns}
            >
                <!-- ... -->
                <Column
                    dataField="Picture"
                    cellRender={cellRender} <!-- This code works correctly -->
                />
            </DataGrid>
        );
    }
}

function cellRender(data) {
    return <img src={data.value} />;
}

export default App;

Specifies a custom template for data rows.

Selector: data-row-template

Binds the UI component to data.

Selector: data-source

Default Value: null

The DataGrid works with collections of objects. We recommend that you use a plain object in data (no circulars, no prototypes, etc.). The DataGird uses JSON.stringify and other recursive methods. Circular object references can crash native recursive algorithms (such as serializers) with stack overflows.

Depending on your data source, bind DataGrid to data as follows.

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:

jQuery Angular Vue React

Specifies the format in which date-time values should be sent to the server.

Selector: date-serialization-format

Specify this property in the following cases:

Use one of the following values to specify the dateSerializationFormat property:

This property applies only if the forceIsoDateParsing field is set to true in the global configuration object.

See Also

Specifies whether the UI component responds to user interaction.

Configures 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.

Before allowing a user to add, update, and delete, make sure that your

data source

supports these actions.

View Demo

See Also

Specifies the global attributes to be attached to the UI component's container element.

Selector: DxElementAttr

Default Value: {}

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;

Indicates whether to show the error row.

Selector: error-row-enabled

Default Value: true

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

Configures client-side exporting.

A user can click the Export button to save an Excel or PDF file with the exported data. Data types, sort, filter, and group settings are maintained.

The following instructions show how to enable and configure client-side export:

  1. Install or reference the required libraries

    Install the following libraries for the export:

    jQuery
    <!-- Export to Excel -->
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.0/polyfill.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/devextreme-exceljs-fork@4.4.1/dist/dx-exceljs-fork.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.2/FileSaver.min.js"></script>
        <!-- Reference the DevExtreme sources here -->
    </head>
    
    <!-- Export to Pdf -->
    <head>
        <!-- ... -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.0.0/jspdf.umd.min.js"></script>
        <!-- Reference the DevExtreme sources here -->
    </head>
    Angular
    <!-- Export to Pdf  -->
    npm install jspdf
    
    <!-- Export to Excel -->
    npm install --save devextreme-exceljs-fork file-saver
    npm i --save-dev @types/file-saver
    <!-- Export to Excel -->
    {
        "compilerOptions": {
            // ...
            "outDir": "./out-tsc/app",
            "types": ["node"]
        },
    }
    Vue
    <!-- Export to Pdf  -->
    npm install jspdf
    
    <!-- Export to Excel -->
    npm install --save devextreme-exceljs-fork file-saver
    React
    <!-- Export to Pdf  -->
    npm install jspdf
    
    <!-- Export to Excel -->
    npm install --save devextreme-exceljs-fork file-saver
  2. 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
    $(function () {
        $("#dataGridContainer").dxDataGrid({
            export: {
                enabled: true
            },
            columns: [{ ...
                allowExporting: false
            }, 
                // ...
            ]
        });
    });
    Angular
    <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
    <template>
        <DxDataGrid ... >
            <DxExport
                :enabled="true"
            />
            <DxColumn ... 
                :allow-exporting="false"
            />
        </DxDataGrid>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import { DxDataGrid, 
        DxExport,
        DxColumn
    } from 'devextreme-vue/data-grid';
    
    export default {
        components: {
            DxDataGrid,
            DxExport,
            DxColumn
        }
    }
    </script>
    React
    import React from 'react';
    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;
  3. Export the DataGrid
    Implement the onExporting handler and call the excelExporter.exportDataGrid(options) or pdfExporter.exportDataGrid(options) method. In the code below, the exportDataGrid method exports the DataGrid as is. You can use ExcelExportDataGridProps/PdfExportDataGridProps to configure export settings. The DataGrid exports its data to an Excel worksheet or a PDF document. To save the Excel document, call the FileSaver's saveAs method. To save the PDF document, call the jsPDF's save method.

    The example below shows how to export DataGrid to Excel file.

    jQuery
    $('#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) {
                    options.excelCell.font = { name: 'Arial', size: 12 };
                    options.excelCell.alignment = { horizontal: 'left' };
                } 
            }).then(function() {
                workbook.xlsx.writeBuffer().then(function(buffer) { 
                    saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); 
                }); 
            }); 
        }
    });
    Angular
    <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 'devextreme-exceljs-fork';
    import { saveAs } from 'file-saver';
    import { ExportingEvent } from 'devextreme/ui/data_grid';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    export class AppComponent {
        onExporting(e: ExportingEvent) {
            const workbook = new Workbook();    
            const worksheet = workbook.addWorksheet('Main sheet');
            exportDataGrid({
                component: e.component,
                worksheet: worksheet,
                customizeCell: function(options) {
                    options.excelCell.font = { name: 'Arial', size: 12 };
                    options.excelCell.alignment = { horizontal: 'left' };
                } 
            }).then(function() {
                workbook.xlsx.writeBuffer()
                    .then(function(buffer: BlobPart) {
                        saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
                    });
            });
        }
    }
    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"
            />
        </DxDataGrid>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import { DxDataGrid, DxExport } from 'devextreme-vue/data-grid';
    import { exportDataGrid } from 'devextreme/excel_exporter';
    import { Workbook } from 'devextreme-exceljs-fork';
    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) {
                        options.excelCell.font = { name: 'Arial', size: 12 };
                        options.excelCell.alignment = { horizontal: 'left' };
                    } 
                }).then(function() {
                    workbook.xlsx.writeBuffer()
                        .then(function(buffer) {
                            saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
                        });
                });
            }
        }
    }
    </script>
    React
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    
    import { Workbook } from 'devextreme-exceljs-fork';
    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) {
                    options.excelCell.font = { name: 'Arial', size: 12 };
                    options.excelCell.alignment = { horizontal: 'left' };
                } 
            }).then(function() {
                workbook.xlsx.writeBuffer()
                    .then(function(buffer) {
                        saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
                    });
            });
        }
    }
    export default App;

    The example below shows how to export DataGrid to PDF document.

    jQuery
    $(function(){
        $('#exportButton').dxButton({
            // ...
            onClick: function() {
                const doc = new jsPDF();
                DevExpress.pdfExporter.exportDataGrid({
                    jsPDFDocument: doc,
                    component: dataGrid
                }).then(function() {
                    doc.save('Customers.pdf');
                });
            }
        });
        const dataGrid = $('#gridContainer').dxDataGrid({
            // ...
        }).dxDataGrid('instance');
    });
    Angular
    <dx-button ... 
        (onClick)="exportGrid($event)">
    </dx-button>
    
    <dx-data-grid ... >
        <!-- ... -->
    </dx-data-grid>
    import { Component } from '@angular/core';
    import { exportDataGrid as exportDataGridToPdf } from 'devextreme/pdf_exporter';
    import { jsPDF } from 'jspdf';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    export class AppComponent {
        @ViewChild(DxDataGridComponent, { static: false }) dataGrid: DxDataGridComponent;
        exportGrid() {
            const doc = new jsPDF();
            exportDataGridToPdf({
                jsPDFDocument: doc,
                component: this.dataGrid.instance
            }).then(() => {
                doc.save('Customers.pdf');
            })
        }
    }
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { DxDataGridModule, DxButtonModule } from 'devextreme-angular';
    
    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            BrowserModule,
            DxDataGridModule,
            DxButtonModule
        ],
        providers: [ ],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    Vue
    <template>
        <div>
            <DxButton ...
                @click="exportGrid()"
            />
            <DxDataGrid ...
                :ref="dataGridRef">
                <!-- ... -->
            </DxDataGrid>
        </div>
    </template>
    
    <script>
    import 'devextreme/dist/css/dx.light.css';
    
    import DxDataGrid from 'devextreme-vue/data-grid';
    import DxButton from 'devextreme-vue/button';
    import { jsPDF } from 'jspdf';
    import { exportDataGrid as exportDataGridToPdf } from 'devextreme/pdf_exporter';
    const dataGridRef = 'dataGrid';
    export default {
        components: {
            DxDataGrid,
            DxButton
        },
        data() {
            return {
                dataGridRef
            };
        },
        computed: {
            dataGrid: function() {
                return this.$refs[dataGridRef].instance;
            }
        },
        methods: {
            exportGrid() {
                const doc = new jsPDF();
                exportDataGridToPdf({
                    jsPDFDocument: doc,
                    component: this.dataGrid
                }).then(() => {
                    doc.save('Customers.pdf');
                });
            }
        }
    }
    </script>
    React
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    
    import DataGrid from 'devextreme-react/data-grid';
    import Button from 'devextreme-react/button';
    import { jsPDF } from 'jspdf';
    import { exportDataGrid as exportDataGridToPdf } from 'devextreme/pdf_exporter';
    export default function App() {
        const dataGridRef = useRef(null);
        function exportGrid() {
            const doc = new jsPDF();
            const dataGrid = dataGridRef.current.instance();
            exportDataGridToPdf({
                jsPDFDocument: doc,
                component: dataGrid
            }).then(() => {
                doc.save('Customers.pdf');
            });
        }
        return (
            <React.Fragment>
                <div>
                    <Button ...
                        onClick={exportGrid}
                    />
                    <DataGrid ...
                        ref={dataGridRef}
                        >
                        {/* ... */}
                    </DataGrid>
                </div>
            </React.Fragment>
        );
    }

The following restrictions apply when users export DataGrid:

Export to Excel Overview Demo Export to PDF Overview Demo Export Images to Excel Demo Export Images to PDF Demo

Configures the integrated filter builder.

Selector: DxFilterBuilder

Default Value: {}

See the FilterBuilder configuration for properties that you can specify in this object. Do not specify the fields array because the DataGrid automatically populates it to sync filter builder fields with grid columns.

Angular

The nested component that configures the filterBuilder property does not support event bindings and two-way property bindings.

Vue

The nested component that configures the filterBuilder property does not support event bindings and two-way property bindings.

View Demo

See Also

Configures the popup in which the integrated filter builder is shown.

Selector: DxFilterBuilderPopup

Default Value: {}

See the Popup configuration for properties that you can specify in this object.

View Demo

Angular

The nested component that configures the filterBuilderPopup property does not support event bindings and two-way property bindings.

Vue

The nested component that configures the filterBuilderPopup property does not support event bindings and two-way property bindings.

See Also

Configures the filter panel.

Selector: DxFilterPanel

Default Value: {}

Configures the filter row.

Specifies whether to synchronize the filter row, header filter, and filter builder. The synchronized filter expression is stored in the filterValue property.

Selector: filter-sync-enabled

Default Value: 'auto'

Synchronization is enabled if the filter panel is visible. When it is enabled, check that each column that allows filter operations has the dataField or name property specified.

If this property is enabled, the component keeps filters specified in header filters and filter rows active when columns are hidden.

Specifies a filter expression.

Selector: filter-value

Default Value: null

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.

Note that you should convert date strings into JavaScript Date objects before using them in the filter expression.

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.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.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.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.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));
        // ...
    })
)

The

DataSource

does not support the

"between"

,

"anyof"

,

"noneof"

, and custom operations. Use the

getCombinedFilter(returnDataField)

method to get the

DataSource

-compatible filter expression.

See Also

The index of the column that contains the focused data cell. This index is taken from the columns array.

Selector: focused-column-index

Default Value: -1

Specifies whether the focused row feature is enabled.

Selector: focused-row-enabled

Default Value: false

The component relies on the key (focusedRowKey) or index (focusedRowIndex) of the focused row to maintain focus. Specify the key to ensure the focused row feature works correctly, as row indexes can change due to filtering or sorting operations. Utilize keyExpr or the key property of the component's store.

The focused row can change if it is hidden by filtering or searching operations. To maintain focus on the same row through filtering and searching operations, set

selection

.

mode

to "single" instead of enabling

focusedRowEnabled

.

The component navigates to the page of the focused row and scrolls to it automatically when you modify focusedRowKey or focusedRowIndex. Assign false to autoNavigateToFocusedRow to disable this behavior.

DataGrid generates requests with comparison operators (such as < and >) to calculate the page number of the focused row. This logic does not work for certain key types (such as GUID) and data providers (such as ODataStore). Disable remoteOperations to ensure the component navigates to the focused row correctly.

View Demo

See Also

Specifies or indicates the focused data row's index.

Selector: focused-row-index

Default Value: -1

Specifies initially or currently focused grid row's key.

Selector: focused-row-key

Type: any | undefined

Default Value: undefined

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.

Record Grouping Demo Remote Grouping Demo

See Also

Configures the header filter feature.

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.

If a column has empty cells (null, undefined, or ''), the header filter adds a "(Blanks)" item to its data source. To avoid displaying this "(Blanks)" item, implement DataSource.postProcess in the columns.headerFilter.dataSource method:

jQuery
$(function() {
    $("#dataGridContainer").dxDataGrid({
        columns: [{
            headerFilter: {
                dataSource: function (options) {
                    options.dataSource.postProcess = function (results) {
                        return results.filter((item) => item.value !== null)
                    }
                }
            }
        }]
    })
})
Angular
<dx-data-grid ... >
    <dxo-header-filter [visible]="true"></dxo-header-filter>
    <dxi-column ... >
        <dxo-header-filter ... 
            [dataSource]="calculateDataSource"
        ></dxo-header-filter>
    </dxi-column>
</dx-data-grid>
export class AppComponent {
    calculateDataSource (options) {
        options.dataSource.postProcess = function (results) {
            return results.filter((item) => item.value !== null)
        }
    }
}
Vue
<template>
    <DxDataGrid ... >
        <DxHeaderFilter :visible="true" />
        <DxColumn ... >
            <DxHeaderFilter ...
                :data-source="calculateDataSource"
            />
        </DxColumn>
    </DxDataGrid>
</template>

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

const calculateDataSource = (options) => {
    options.dataSource.postProcess = function (results) {
        return results.filter((item) => item.value !== null)
    }
}
</script>
React
import DataGrid, { Column, Lookup, HeaderFilter } from 'devextreme-react/data-grid';

function calculateDataSource(options) {
    options.dataSource.postProcess = function (results) {
        return results.filter((item) => item.value !== null)
    }
}

export default function App() {
    return (
        <DataGrid ... >
            <HeaderFilter visible={true} />
            <Column ...
                <HeaderFilter ...
                    dataSource={calculateDataSource}
                />
            </Column>
        </DataGrid>
    );
}

The user's filtering preferences are saved in the filterValues property. The header filter's Select All checkbox changes the filterType property.

DataGrid Demo TreeList Demo

See Also

Specifies the UI component's height.

This property accepts a value of one of the following types:

DataGrid does not support the

transform: scale

CSS rule. Specify height and

width

as a percentage instead.

Specifies whether to highlight rows and cells with edited data. repaintChangesOnly should be true.

Selector: highlight-changes

Default Value: false

Collaborative Editing Demo SignalR Service Demo

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;
}

Specifies text for a hint that appears when a user pauses on the UI component.

Specifies whether to highlight rows when a user moves the mouse pointer over them.

Selector: hover-state-enabled

Default Value: false

View Demo

Configures keyboard navigation.

Selector: DxKeyboardNavigation

View Demo

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.

Selector: key-expr

Default Value: undefined

Configures the load panel.

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

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.

Master-Detail View Demo Advanced Master-Detail View Demo

See Also

Specifies a text string shown when the DataGrid does not display any data.

Selector: no-data-text

Default Value: 'No data'

A function that is executed before an adaptive detail row is rendered.

Selector: @adaptive-detail-row-preparing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

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.

jQuery
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        onAdaptiveDetailRowPreparing: function(e) {
            e.formOptions.colCount = 2;
            e.formOptions.colCountByScreen = {
                xs: 2
            }
            e.formOptions.labelLocation = 'left';
        }
    })
})
Angular
import { DxDataGridModule } from "devextreme-angular";
// ...
export class AppComponent {
    onAdaptiveDetailRowPreparing(e) {
        e.formOptions.colCount = 2;
        e.formOptions.colCountByScreen = {
            xs: 2
        }
        e.formOptions.labelLocation = 'left';
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
<dx-data-grid ...
    (onAdaptiveDetailRowPreparing)="onAdaptiveDetailRowPreparing($event)">
</dx-data-grid>
Vue

App.vue (Composition API)

<template>
    <DxDataGrid
        @adaptive-detail-row-preparing="onAdaptiveDetailRowPreparing"
    />
</template>

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

import DataGrid from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid
    },
    methods: {
        onAdaptiveDetailRowPreparing(e) {
            e.formOptions.colCount = 2;
            e.formOptions.colCountByScreen = {
                xs: 2
            }
            e.formOptions.labelLocation = 'left';
        }
    }
}
</script>
<template>
    <DxDataGrid
        @adaptive-detail-row-preparing="onAdaptiveDetailRowPreparing"
    />
</template>

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

import DataGrid from 'devextreme-vue/data-grid';

const onAdaptiveDetailRowPreparing = (e) => {
    e.formOptions.colCount = 2;
    e.formOptions.colCountByScreen = {
        xs: 2
    }
    e.formOptions.labelLocation = 'left';
}
</script>
React
import { useCallback } from 'react';

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

import DataGrid from 'devextreme-react/data-grid';

export default function App() {
    const onAdaptiveDetailRowPreparing = useCallback((e) => {
        e.formOptions.colCount = 2;
        e.formOptions.colCountByScreen = {
            xs: 2
        }
        e.formOptions.labelLocation = 'left';
    }, []);

    return (
        <DataGrid
            onAdaptiveDetailRowPreparing={onAdaptiveDetailRowPreparing}
        />
    );
}
See Also

A function that is executed when a cell is clicked or tapped. Executed before onRowClick.

Selector: @cell-click

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

View on GitHub

A function that is executed when a cell is double-clicked or double-tapped. Executed before onRowDblClick.

Selector: @cell-dbl-click

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description cellElement

HTMLElement | jQuery

The cell's container. It is an HTML Element or a jQuery Element when you use jQuery.

column

DataGrid Column

The column's configuration.

columnIndex

Number

The index of the column the cell belongs to. For details on indexes, see the Column and Row Indexes topic.

component

DataGrid

The UI component's instance.

data

Object

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".
Differs from the value field only when the cell belongs to a lookup column.

element

HTMLElement | jQuery

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 an EventObject 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".

row

DataGrid Row

The row's properties. Available if the rowType is "data", "detail", "detailAdaptive", or "group".

rowIndex

Number

The index of the row the cell belongs to.

rowType

String

The row's type.

text

String

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".

Default Value: null

A function that is executed after the pointer enters or leaves a cell.

Selector: @cell-hover-changed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

To identify whether the pointer has entered or left the cell, check the eventType field's value.

View on GitHub

A function that is executed after a grid cell is created.

Selector: @cell-prepared

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description cellElement

HTMLElement | jQuery

The cell's container. It is an HTML Element or a jQuery Element when you use jQuery.

column

DataGrid Column

This column's configuration.

columnIndex

Number

The visible column index described in the following topic: Column and Row Indexes.

component

DataGrid

The UI component's instance.

data

Object

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. Available if the rowType is "data".
Differs from the value field only when the column to which the prepared cell belongs uses lookup.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

isExpanded

Boolean

Indicates whether the row is expanded or collapsed. Available if rowType is "data" or "group".

isNewRow

Boolean

Indicates that the row is added, but not yet saved. Available if rowType is "data".

isSelected

Boolean

Indicates whether the row is selected. Available if rowType is "data" or "detail".

key any

The row's key. Unavailable if rowType is "header", "filter", or "totalFooter".
If a field providing keys is not specified in the data source, the whole data object is considered the key.

oldValue any

The cell's previous raw value. Defined only if repaintChangesOnly is true.

row

DataGrid Row

Row properties.

rowIndex

Number

The row's index. Refer to Column and Row Indexes for more information.

rowType

String

The row's type.

text

String

The cell's formatted value converted to a string. Available if the rowType is "data".

value any

The cell's raw value. Available if the rowType is "data".

watch

Function

Allows you to track a variable and execute actions when it changes. Applies when repaintChangesOnly is true.
This function has the following parameters:

Default Value: null

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.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.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>

To learn how to use onCellPrepared to display a tooltip for data cells, refer to the following example:

View on GitHub

To learn how to implement conditional formatting with onCellPrepared, refer to the following example:

View on GitHub

See Also

A function that is executed when the UI component is rendered and each time the component is repainted.

Selector: @content-ready

Function parameters:

Information about the event.

Object structure:

Default Value: null

A function that is executed before the context menu is rendered.

Selector: @context-menu-preparing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

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.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.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;

View on GitHub

A function that is executed when an error occurs in the data source.

Selector: @data-error-occurred

Function parameters:

Information on the occurred error.

Object structure:

Default Value: null

Handles errors that might occur in the data source. To obtain a human-readable description of the error in the function, use the error.message field.

A function that is executed before the UI component is disposed of.

Selector: @disposing

Function parameters:

Information about the event.

Object structure:

Default Value: null

A function that is executed after row changes are discarded.

Selector: @edit-canceled

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

View Demo

A function that is executed when the edit operation is canceled, but row changes are not yet discarded.

Selector: @edit-canceling

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description changes

Array<DataChange>

Row changes to be discarded.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

cancel

Boolean

Set this field to true if the row changes should not be discarded.

Default Value: null

An edit operation can be canceled from the UI (with the Cancel button) or programatically (with the cancelEditData() method).

View Demo

A function that is executed before a cell or row switches to the editing state.

Selector: @editing-start

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description cancel

Boolean

Allows you to cancel row editing.

column

Object

The configuration of the column whose cell is switching to the editing state. Available in the "cell" and "batch" editing modes.

component

DataGrid

The UI component's instance.

data

Object

The data of a row to be edited.

element

HTMLElement | jQuery

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.
If a field providing keys is not specified in the data source, the whole data object is considered the key.

Default Value: null

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.

View Demo

A function that is executed after an editor is created. Not executed for cells with an editCellTemplate.

Selector: @editor-prepared

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description component

DataGrid

The UI component's instance.

dataField

String

The name of the field that provides data for the column the editor belongs to.

disabled

Boolean

Indicates whether the editor is disabled.

editorElement

HTMLElement | jQuery

The editor's container. It is an HTML Element or a jQuery Element when you use jQuery.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

parentType

String

The editor's location. One of "dataRow", "filterRow", "headerRow" or "searchPanel".
Options passed to the function depend on this value.

readOnly

Boolean

Indicates whether the editor is read-only.

row

DataGrid Row

The properties of the row the editor belongs to.

rtlEnabled

Boolean

Indicates whether the editor uses right-to-left representation.

setValue any

A method you should call to change the cell value and, optionally, the displayed value after the editor's value is changed.

updateValueTimeout

Number

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

Number

The editor's width; equals null for all editors except for those whose parentType equals "searchPanel".

Default Value: null

View on GitHub

A function used to customize cell editors. Not executed for cells with an editCellTemplate.

Selector: @editor-preparing

Function parameters:

Information about the event that caused function execution.

Object structure:

Name Type Description cancel

Boolean

Allows you to cancel editor creation.
You can set this field's value to true and implement a custom editor.

component

DataGrid

UI component instance.

dataField

String

The field name that supplies data for the column editor.

disabled

Boolean

Indicates whether the editor is disabled.

editorElement

HTMLElement | jQuery

The editor's container. It is an HTML Element or a jQuery Element when you use jQuery.

editorName

String

Allows you to change the editor. Accepts names of DevExtreme UI components only, for example, "dxTextBox".
Import a new editor's module when DevExtreme modules are used.

editorOptions

Object

Gets and sets editor configuration.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

parentType

String

Editor location. Can be "dataRow", "filterRow", "headerRow" or "searchPanel".
Properties passed to the onEditorPreparing function depend on this value.

readOnly

Boolean

Indicates whether the editor is read-only.

row

DataGrid Row

Row editor properties.

rtlEnabled

Boolean

Indicates whether the editor uses right-to-left representation.

setValue any

Use this method to change the cell/editor value. You can also pass a second parameter to change cell values in columns with calculateDisplayValue specified.

updateValueTimeout

Number

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

Editor value. This field is read-only. To change the editor value, use the setValue(newValue) function parameter.

width

Number

Editor width; equals null for all editors except for those whose parentType equals "searchPanel".

Default Value: null

Use this function to:

View Demo

See Also

A function that is executed before data is exported.

Selector: @exporting

Function parameters:

Information about the event that caused the function execution.

Object structure:

Default Value: null

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 to an Excel file.

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();
            });
        }
    });
});
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 'devextreme-exceljs-fork';
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();
        });
    }
}
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.light.css';

import { DxDataGrid, DxExport, DxColumn } from 'devextreme-vue/data-grid';
import { exportDataGrid } from 'devextreme/excel_exporter';
import { Workbook } from 'devextreme-exceljs-fork';
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();
            });
        }
    }
}
</script>
React
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import { Workbook } from 'devextreme-exceljs-fork';
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();
        });
    }
}
export default App;

Export to Excel Overview Demo Export to PDF Overview Demo

See Also

A function that is executed after the focused cell changes. Applies only to cells in data or group rows.

Selector: @focused-cell-changed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function that is executed before the focused cell changes. Applies only to cells in data or group rows.

Selector: @focused-cell-changing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description cancel

Boolean

Allows you to cancel focusing a new cell.

cellElement

HTMLElement | jQuery

The to-be-focused cell's container. It is an HTML Element or a jQuery Element when you use jQuery.

columns

Array<DataGrid Column>

The visible columns' properties.

component

DataGrid

The UI component's instance.

element

HTMLElement | jQuery

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 an EventObject or a jQuery.Event when you use jQuery.

isHighlighted

Boolean

true if the cell is highlighted; otherwise false, even if the cell's row is highlighted.

newColumnIndex

Number

The index of the column the cell that should be focused belongs to.

newRowIndex

Number

The index of the row the cell that should be focused belongs to.

prevColumnIndex

Number

The index of the previously focused cell's column.

prevRowIndex

Number

The index of the previously focused cell's row.

rows

Array<DataGrid Row>

The visible rows' properties.

Default Value: null

View Demo

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.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.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

A function that is executed after the focused row changes. Applies only to data or group rows. focusedRowEnabled should be true.

Selector: @focused-row-changed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function that is executed before the focused row changes. Applies only to data or group rows. focusedRowEnabled should be true.

Selector: @focused-row-changing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function used in JavaScript frameworks to save the UI component instance.

Selector: @initialized

Function parameters:

Information about the event.

Object structure:

Default Value: null

Angular
<dx-data-grid ...
    (onInitialized)="saveInstance($event)">
</dx-data-grid>
import { Component } from "@angular/core";
import DataGrid from "devextreme/ui/data_grid";
// ...
export class AppComponent {
    dataGridInstance: DataGrid;
    saveInstance (e) {
        this.dataGridInstance = e.component;
    }
}
Vue

App.vue (Composition API)

<template>
    <div>
        <DxDataGrid ...
            @initialized="saveInstance">
        </DxDataGrid>
    </div>
</template>

<script>
import DxDataGrid from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid
    },
    data: function() {
        return {
            dataGridInstance: null
        };
    },
    methods: {
        saveInstance: function(e) {
            this.dataGridInstance = e.component;
        }
    }
};
</script>
<template>
    <div>
        <DxDataGrid ...
            @initialized="saveInstance">
        </DxDataGrid>
    </div>
</template>

<script setup>
import DxDataGrid from 'devextreme-vue/data-grid';

let dataGridInstance = null;

const saveInstance = (e) => {
    dataGridInstance = e.component;
}
</script>
React
import DataGrid from 'devextreme-react/data-grid';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.saveInstance = this.saveInstance.bind(this);
    }

    saveInstance(e) {
        this.dataGridInstance = e.component;
    }

    render() {
        return (
            <div>
                <DataGrid onInitialized={this.saveInstance} />
            </div>
        );
    }
}
See Also jQuery Angular Vue React

A function that is executed before a new row is added to the UI component.

Selector: @init-new-row

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description promise

Promise<void> (jQuery or native)

Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.

data

Object

The data of the inserted row; initially empty.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

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.

DataGrid Demo TreeList Demo

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';
import { lastValueFrom } from 'rxjs';

@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 lastValueFrom(this.httpClient.get("https://www.mywebsite.com/api/getDefaultData"))
            .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.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.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>

A function that is executed when the UI component is in focus and a key has been pressed down.

Selector: @key-down

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

The following code shows how to handle a key combination:

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.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.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;

A function that is executed after a UI component property is changed.

Selector: @option-changed

Function parameters:

Information about the event.

Object structure:

Name Type Description value any

The modified property's new value.

previousValue any

The UI component's previous value.

name

String

The modified property if it belongs to the first level. Otherwise, the first-level property it is nested into.

fullName

String

The path to the modified property that includes all parent properties.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

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.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.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}
        />        
    ); 
} 

A function that is executed when a row is clicked or tapped.

Selector: @row-click

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

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.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.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>

The onRowClick function is not executed when the clicked row enters or is in the editing state. Instead, specify the onCellClick function.

A function that is executed after a row is collapsed.

Selector: @row-collapsed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function that is executed before a row is collapsed.

Selector: @row-collapsing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

To cancel row collapsing, assign true to the cancel field of the function parameter.

A function that is executed when a row is double-clicked or double-tapped. Executed after onCellDblClick.

Selector: @row-dbl-click

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description columns

Array<DataGrid Column>

The configurations of visible columns.

component

DataGrid

The UI component's instance.

data

Object

The row's data.

element

HTMLElement | jQuery

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 an EventObject or a jQuery.Event when you use jQuery.

groupIndex

Number

The row's group index. Available if rowType is "group".

isExpanded

Boolean

Indicates whether the row is expanded or collapsed. Available if rowType is "data" or "group".

isNewRow

Boolean

Indicates that the row is added, but not yet saved. Available if rowType is "data".

isSelected

Boolean

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".

rowElement

HTMLElement | jQuery

The row's container. It is an HTML Element or a jQuery Element when you use jQuery.

rowIndex

Number

The row's index. Refer to Column and Row Indexes for more information.

rowType

String

The row's type.

values

Array<any>

Raw values displayed in the row's cells.

Default Value: null

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>

A function that is executed after a row is expanded.

Selector: @row-expanded

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function that is executed before a row is expanded.

Selector: @row-expanding

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

To cancel row expansion, assign true to the cancel field of the function parameter.

A function that is executed after a new row has been inserted into the data source.

Selector: @row-inserted

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description 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.

error

JavaScript Error Object

The standard Error object defining an error that may occur during insertion.

data

Object

The data of the row.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

View Demo

In batch

editing mode

, if several rows have been inserted, this function will be executed for each row individually.

A function that is executed before a new row is inserted into the data source.

Selector: @row-inserting

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description data

Object

The data of the row that should be inserted.

cancel

Boolean

|

Promise<Boolean> (jQuery or native)

|

Promise<void> (jQuery or native)

true, a Promise resolved with true, or a rejected Promise stops row insertion.
false or a Promise resolved with false or undefined continues row insertion.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

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';
import { lastValueFrom } from 'rxjs';
// ...

export class AppComponent {
    constructor(private httpClient: HttpClient) { /*...*/ }
    async insertRow(e) {
        try {
            const dialogResult = await this.confirmAsync("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 lastValueFrom(this.httpClient.get("https://url/to/your/validation/service", { params }));
                if (validationResult.errorText) {
                    throw validationResult.errorText;
                } else {
                    e.cancel = false;
                }
            } else {
                e.cancel = true;
            }
        } catch (error) {
            console.error("Validation or confirmation error", error);
            e.cancel = Promise.reject(error);
        }
    }

    private confirmAsync(message: string, title?: string): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            const dialogResult = confirm(message, title);
            resolve(dialogResult);
        });
    }
}
<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 { confirm } from 'devextreme/ui/dialog';
// ...

export default {
    components: {
        DxDataGrid,
        // ...
    },
    // ...
    methods: {
        insertRow(e) {
            const isCanceled = new Promise((resolve, reject) => {
                const promptPromise = confirm("Are you sure?", "Confirm changes");
                promptPromise.then((dialogResult) => {
                    if (dialogResult) {
                        let params = new HttpParams();
                        for (let key in e.newData) {
                            params = params.set(key, e.newData[key]);
                        }
                        fetch(`https://url/to/your/validation/service${params}`)
                            .then((validationResult) => {
                                if (validationResult.errorText) {
                                    reject(validationResult.errorText);
                                } else {
                                    resolve(false);
                                } 
                            });
                    } else {
                        return resolve(true);
                    }
                });
            });
            e.cancel = isCanceled;
        }
    },
};
</script>
React
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import { confirm } from 'devextreme/ui/dialog';
import DataGrid, { ... } from 'devextreme-react/data-grid';

function insertRow(e) {
    const isCanceled = new Promise((resolve, reject) => {
        const promptPromise = confirm("Are you sure?", "Confirm changes");
        promptPromise.then((dialogResult) => {
            if (dialogResult) {
                let params = new HttpParams();
                for (let key in e.newData) {
                    params = params.set(key, e.newData[key]);
                }
                fetch(`https://url/to/your/validation/service${params}`)
                    .then((validationResult) => {
                        if (validationResult.errorText) {
                            reject(validationResult.errorText);
                        } else {
                            resolve(false);
                        } 
                    });
            } else {
                return resolve(true);
            }
        });
    });
    e.cancel = isCanceled;
}

function App() {
    return (
        <DataGrid ...
            onRowInserting={insertRow}>
            // ...
        </DataGrid>
    );
}

export default App;

A function that is executed after a row is created.

Selector: @row-prepared

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

A function that is executed after a row has been removed from the data source.

Selector: @row-removed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description 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.

error

JavaScript Error Object

The standard Error object defining an error that may occur during removal.

data

Object

The data of the row.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

View Demo

In batch

editing mode

, if several rows have been removed, this function will be executed for each row individually.

A function that is executed before a row is removed from the data source.

Selector: @row-removing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description key any

The row's key.

data

Object

The data of the row that should be removed.

cancel

Boolean

|

Promise<Boolean> (jQuery or native)

|

Promise<void> (jQuery or native)

true, a Promise resolved with true, or a rejected Promise stops row removal.
false or a Promise resolved with false or undefined continues row removal.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

In batch

editing mode

, this function is executed for each row individually if several rows should be removed.

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";
import { lastValueFrom } from 'rxjs';

export class AppComponent {
    constructor(private httpClient: HttpClient) { /*...*/ }
    validateRemove(e) {
        const isCanceled = new Promise((resolve, reject) => {
            const request$ = this.httpClient
                .get(`https://url/to/your/validation/service/${e.key}`);

            lastValueFrom(request$).then((validationResult) => {
                if (validationResult.errorText) {
                    reject(validationResult.errorText);
                } else {
                    resolve(false);
                }
            });
        });
        e.cancel = 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';
// ...

export default {
    components: {
        DxDataGrid,
        // ...
    },
    // ...
    methods: {
        validateRemove(e) {
            const isCanceled = new Promise((resolve, reject) => {
                fetch(`https://url/to/your/validation/service/${e.key}`)
                    .then((validationResult) => {
                        if (validationResult.errorText) {
                            reject(validationResult.errorText);
                        } else {
                            resolve(false);
                        }
                    });
            });
            e.cancel = isCanceled;
        }
    },
};
</script>
React
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

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

function validateRemove(e) {
    const isCanceled = new Promise((resolve, reject) => {
        fetch(`https://url/to/your/validation/service/${e.key}`)
            .then((validationResult) => {
                if (validationResult.errorText) {
                    reject(validationResult.errorText);
                } else {
                    resolve(false);
                }
            });
    });
    e.cancel = isCanceled;
}

function App() {
    return (
        <DataGrid ...
            onRowRemoving={validateRemove}>
            // ...
        </DataGrid>
    );
}

export default App;

A function that is executed after a row has been updated in the data source.

Selector: @row-updated

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description 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.

error

JavaScript Error Object

The standard Error object defining an error that may occur during updating.

data

Object

The updated data of the row.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

View Demo

In batch

editing mode

, if several rows have been updated, this function will be executed for each row individually.

A function that is executed before a row is updated in the data source.

Selector: @row-updating

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description oldData

Object

The row's old data.

newData

Object

The row's updated data.

key any

The row's key.

cancel

Boolean

|

Promise<Boolean> (jQuery or native)

|

Promise<void> (jQuery or native)

true, a Promise resolved with true, or a rejected Promise stops row updating.
false or a Promise resolved with false or undefined continues row updating.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

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';
import { lastValueFrom } from 'rxjs';
// ...

export class AppComponent {
    constructor(private httpClient: HttpClient) { /*...*/ }
    async updateRow(e) {
        try {
            const dialogResult = await this.confirmAsync("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 lastValueFrom(this.httpClient.get("https://url/to/your/validation/service", { params }));
                if (validationResult.errorText) {
                    throw validationResult.errorText;
                } else {
                    e.cancel = false;
                }
            } else {
                e.cancel = true;
            }
        } catch (error) {
            console.error("Validation or confirmation error", error);
            e.cancel = Promise.reject(error);
        }
    }

    private confirmAsync(message: string, title?: string): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            const dialogResult = confirm(message, title);
            resolve(dialogResult);
        });
    }
}
<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 { confirm } from 'devextreme/ui/dialog';
// ...

export default {
    components: {
        DxDataGrid,
        // ...
    },
    // ...
    methods: {
        updateRow(e) {
            const isCanceled = new Promise((resolve, reject) => {
                const promptPromise = confirm("Are you sure?", "Confirm changes");
                promptPromise.then((dialogResult) => {
                    if (dialogResult) {
                        let params = new HttpParams();
                        for (let key in e.newData) {
                            params = params.set(key, e.newData[key]);
                        }
                        fetch(`https://url/to/your/validation/service${params}`)
                            .then((validationResult) => {
                                if (validationResult.errorText) {
                                    reject(validationResult.errorText);
                                } else {
                                    resolve(false);
                                } 
                            });
                    } else {
                        return resolve(true);
                    }
                });
            });
            e.cancel = isCanceled;
        }
    },
};
</script>
React
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import { confirm } from 'devextreme/ui/dialog';
import DataGrid, { ... } from 'devextreme-react/data-grid';

function updateRow(e) {
    const isCanceled = new Promise((resolve, reject) => {
        const promptPromise = confirm("Are you sure?", "Confirm changes");
        promptPromise.then((dialogResult) => {
            if (dialogResult) {
                let params = new HttpParams();
                for (let key in e.newData) {
                    params = params.set(key, e.newData[key]);
                }
                fetch(`https://url/to/your/validation/service${params}`)
                    .then((validationResult) => {
                        if (validationResult.errorText) {
                            reject(validationResult.errorText);
                        } else {
                            resolve(false);
                        } 
                    });
            } else {
                return resolve(true);
            }
        });
    });
    e.cancel = isCanceled;
}

function App() {
    return (
        <DataGrid ...
            onRowUpdating={updateRow}>
            // ...
        </DataGrid>
    );
}

export default App;

A function that is executed after cells in a row are validated against validation rules.

Selector: @row-validating

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description promise

Promise<void> (jQuery or native)

Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.

oldData any

The data of the validated row before changes.

newData

Object

The data of the validated row after changes.

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.

isValid

Boolean

Indicates whether data in all row cells satisfies the validation rules.

errorText

String

An error message to be displayed.

brokenRules

Array<ValidationRule>

An array of broken rules. The structure of rule objects is described in the Validation Rules section.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

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';
import { lastValueFrom } from 'rxjs';

@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 lastValueFrom(
            this.http.get("https://www.mywebsite.com/api/checkEmail", { params })
        );
    }
}
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.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}");
        }
    }
}
</script>
React
import React from 'react';

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}");
    }

    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>

In batch

editing mode

, if changes in several rows are committed simultaneously, this function is executed for each row.

A function that is executed after row changes are saved.

Selector: @saved

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

View Demo

A function that is executed before pending row changes are saved.

Selector: @saving

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description promise

Promise<void> (jQuery or native)

Assign a Promise to this field to perform an asynchronous operation, such as a request to a server.

changes

Array<DataChange>

Pending row changes; a copy of the editing.changes array.

cancel

Boolean

Set this field to true if the default saving logic should be disabled.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

A save operation can be initiated from the UI (with the Save button) or programatically (with the saveEditData() method).

View Demo

A function that is executed after selecting a row or clearing its selection.

Selector: @selection-changed

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Name Type Description selectedRowsData

Array<Object>

The data of all selected rows.
Does not include calculated values.

selectedRowKeys

Array<any>

The keys of all selected rows.

currentSelectedRowKeys

Array<any>

The keys of the rows that have been selected.

currentDeselectedRowKeys

Array<any>

The keys of the rows whose selection has been cleared.

element

HTMLElement | jQuery

The UI component's container. It is an HTML Element or a jQuery Element when you use jQuery.

component

DataGrid

The UI component's instance.

Default Value: null

This function has the following specifics:

If the

selectedRowKeys

array contains keys not included in the component

dataSource

, DataGrid executes

onSelectionChanged

on initialization.

View Demo

A function that is executed before the toolbar is created.

Selector: @toolbar-preparing

Function parameters:

Information about the event that caused the function's execution.

Object structure:

Default Value: null

If you use DevExtreme ASP.NET components or JQuery in your application, specify this property to get the component's instance. In Angular, Vue, or React, use the toolbar property instead.

jQuery

The following code adds a refresh button to the toolbar:

$(function() {
    $("#container").dxDataGrid({
        // ...
        onToolbarPreparing: function(e) {
            let dataGrid = e.component;
            e.toolbarOptions.items.unshift({
                location: "after",
                widget: "dxButton",
                options: {
                    icon: "refresh",
                    onClick: function() {
                        dataGrid.refresh();
                    }
                }
            });
        }
    });
});

View on GitHub

Configures the pager.

Selector: DxPager

Type: Pager

Function parameters:

allowedPageSizes:

Object structure:

Name Type Description

Array

|

Mode

Specifies the available page sizes in the page size selector.

visible:

Object structure:

Name Type Description

Boolean

|

Mode

Specifies whether the pager is visible.

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.

DataGrid Demo TreeList Demo

See Also

Configures paging.

Selector: DxPaging

Type: common/grids:PagingBase

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.

DataGrid Demo TreeList Demo

See Also

Notifies the DataGrid of the server's data processing operations.

Selector: DxRemoteOperations

Default Value: 'auto'

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 grouping4 remoteOperations: { sorting: true } sorting filtering1 remoteOperations: { grouping: true } grouping, filtering sorting1, summary calculation1 remoteOperations: { summary: true } summary calculation filtering1, sorting2, grouping2

Paging, filtering, and sorting are performed on the server side for the

ODataStore

, but you can change them to the client side by setting the corresponding

remoteOperations

fields to

false

. Other operations are always client-side.

The following restrictions apply to UI component functionality when operations are remote:

Web API Service Demo Custom Service Demo

See Also

Specifies whether to repaint only those cells whose data changed.

Selector: repaint-changes-only

Default Value: false

Specifies whether rows should be shaded differently.

Selector: row-alternation-enabled

Default Value: false

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.

View Demo

Configures row reordering using drag and drop gestures.

View Demo

To learn how to configure drag and drop functionality for multiple rows, refer to the following example:

View on GitHub

To learn how to configure drag and drop functionality for multiple rows between grids, refer to the following example:

View on GitHub

Use the dataRowTemplate property instead.

Specifies a custom template for rows.

Follow these steps to migrate from the deprecated rowTemplate property to the dataRowTemplate property:

jQuery
  1. Rename the rowTemplate property to dataRowTemplate.

  2. Remove <tbody>.

  3. If <tbody> contained custom classes or attributes, use the onRowPrepared to add them to the dataRowTemplate.

  4. If you implemented custom row alternation logic, you can remove it and set the rowAlternationEnabled property to true.

  5. If you implemented custom hover logic, you can remove it. Instead, set the hoverStateEnabled property to true and use the dx-state-hover class to specify custom hover styles.

Before:

$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        rowTemplate: function(container, item) {
            const { data } = item;
            const markup = "<tbody class='dx-row my-custom-class'>" +
                "<tr>" +
                    "<td>" + item.data.id + "</td>" +
                    "<td>" + item.data.name + "</td>" +  
                "</tr>" +
            "</tbody>";
            container.append(markup);
        }
    });
});

After:

$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        dataRowTemplate: function(container, item) {
            const { data } = item;
            const markup = "<tr>" +
                "<td>" + item.data.id + "</td>" +
                "<td>" + item.data.name + "</td>" +  
            "</tr>";

            container.append(markup);
        },
        onRowPrepared: function({ rowElement }) {
            rowElement.addClass("my-custom-class");
        }
    });
});
#dataGridContainer tbody.dx-state-hover {
    background-color: #ebebeb;
}
Angular
  1. Rename the rowTemplate property to dataRowTemplate.

  2. Replace <tbody> with <ng-container>.

  3. If <tbody> contained custom classes or attributes, use the onRowPrepared to add them to the dataRowTemplate.

  4. If you implemented custom row alternation logic, you can remove it and set the rowAlternationEnabled property to true.

  5. If you implemented custom hover logic, you can remove it. Instead, set the hoverStateEnabled property to true and use the dx-state-hover class to specify custom hover styles.

Before:

<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>

After:

<dx-data-grid ...
    id="dataGridContainer"
    dataRowTemplate="dataRowTemplateName"
    (onRowPrepared)="addRowClasses">
    <ng-container *dxTemplate="let item of 'dataRowTemplateName'">
        <tr>
            <td>{{item.data.id}}</td>
            <td>{{item.data.name}}</td>
        </tr>
    </ng-container>
</dx-data-grid>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    addRowClasses({ rowElement }) {
        rowElement.classList.add('my-custom-class');
    }
}
#dataGridContainer tbody.dx-state-hover {
    background-color: #ebebeb;
}
Vue
  1. Rename the rowTemplate property to dataRowTemplate.

  2. In Vue 3, remove <tbody>. In Vue 2, change <tbody> for a <div> with the following attribute: style="display: contents".

  3. If <tbody> contained custom classes or attributes, use the onRowPrepared to add them to the dataRowTemplate.

  4. If you implemented custom row alternation logic, you can remove it and set the rowAlternationEnabled property to true.

  5. If you implemented custom hover logic, you can remove it. Instead, set the hoverStateEnabled property to true and use the dx-state-hover class to specify custom hover styles.

Before:

<template>
    <DxDataGrid ...
        row-template="rowTemplate">
        <!-- Vue 3 -->
        <template #rowTemplate="{ data: { data: { id, name } }">
            <tbody class="dx-row">
                <tr>
                    <td>{{id}}</td>
                    <td>{{name}}</td>
                </tr>
            </tbody>
        </template>

        <!-- Vue 2 -->
        <tbody slot="rowTemplate"
            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>

After:

<template>
    <DxDataGrid ...
        id="dataGridContainer"
        data-row-template="dataRowTemplate"
        @row-prepared="addRowClasses">
        <!-- Vue 3 -->
        <template #dataRowTemplate="{ data: { data: { id, name } }">
            <tr>
                <td>{{id}}</td>
                <td>{{name}}</td>
            </tr>
        </template>

        <!-- Vue 2 -->
        <div slot="dataRowTemplate"
            slot-scope="{ data: { data: { id, name } } }"
            style="display: contents">
            <tr>
                <td>{{id}}</td>
                <td>{{name}}</td>
            </tr>
        </div>
    </DxDataGrid>
</template>
<script>
import { DxDataGrid } from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid
    },
    methods: {
        addRowClasses({ rowElement }) {
            rowElement.classList.add('my-custom-class');
        }
    }
};
</script>
<style>
#dataGridContainer tbody.dx-state-hover {
    background-color: #ebebeb;
}
</style>
React
  1. Rename the rowRender property to dataRowRender.

  2. Replace <tbody> with <React.Fragment>.

  3. If <tbody> contained custom classes or attributes, use the onRowPrepared to add them to the dataRowTemplate.

  4. If you implemented custom row alternation logic, you can remove it and set the rowAlternationEnabled property to true.

  5. If you implemented custom hover logic, you can remove it. Instead, set the hoverStateEnabled property to true and use the dx-state-hover class to specify custom hover styles.

Before:

import DataGrid from 'devextreme-react/data-grid';

const Row = ({ data: { id, name } }) => {
    return (
        <tbody className={"dx-row"}>
            <tr>
                <td>{id}</td>
                <td>{name}</td>
            </tr>
        </tbody>
    );
};

export default function App() {
    return (
        <DataGrid ...
            rowRender={Row}>
        </DataGrid>
    );
}

After:

import DataGrid from 'devextreme-react/data-grid';
import './App.css'

const Row = ({ data: { id, name } }) => {
    return (
        <React.Fragment>
            <tr>
                <td>{id}</td>
                <td>{name}</td>
            </tr>
        </React.Fragment>
    );
};

const addRowClasses = ({ rowElement }) => {
    rowElement.classList.add('my-custom-class');
};

export default function App() {
    return (
        <DataGrid ...
            id="dataGridContainer"
            dataRowRender={Row}
            onRowPrepared={addRowClasses}>
        </DataGrid>
    );
}

<!-- App.css -->
#dataGridContainer tbody.dx-state-hover {
    background-color: #ebebeb;
}

Switches the UI component to a right-to-left representation.

Selector: rtl-enabled

Default Value: false

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
});

DataGrid Demo Navigation UI Demo Editors Demo

Configures the search panel.

Allows you to select rows or determine which rows are selected. Applies only if selection.deferred is false.

Selector: selected-row-keys

Configures runtime selection.

Specifies filters for the rows that must be selected initially. Applies only if selection.deferred is true.

Selector: selection-filter

Default Value: []

Specifies whether the outer borders of the UI component are visible.

Selector: show-borders

Default Value: false

Specifies whether column headers are visible.

Selector: show-column-headers

Default Value: true

Specifies whether vertical lines that separate one column from another are visible.

Selector: show-column-lines

Default Value: true, false (Fluent, Material)

View Demo

If you use the Android or iOS theme, specifying this property doesn't affect anything. These themes avoid displaying column lines in order to provide a native look for the UI component. In case you still require the column lines to be displayed, choose

another theme

.

See Also

Specifies whether horizontal lines that separate one row from another are visible.

Selector: show-row-lines

Default Value: false, true (Fluent, Material, iOS)

Allows you to sort groups according to the values of group summary items.

Selector: DxSortByGroupSummaryInfo

Default Value: undefined

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.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.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.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.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.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.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.

This feature does not work when

remoteOperations

.

groupPaging

is set to

true

.

View Demo

See Also

Configures runtime sorting.

A user can sort rows by values of a single or multiple columns depending on the value of the sorting.mode property.

To apply sorting to a column, a user clicks its header or selects a command from the context menu.

View Demo

See Also

Configures state storing.

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:

View Demo View on GitHub

See Also

Specifies the properties of the grid 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.

Group Summaries Demo Total Summaries Demo

Specifies whether to show only relevant values in the header filter and filter row.

Selector: sync-lookup-filter-values

Default Value: true

The following table shows how the component behaves when you assign different values to this property. The 'State' column is filtered by the 'Alabama' value. If you set the syncLookupFilterValues to false, the 'City' column's header filter and filter row display all cities instead of showing cities within Alabama only.

Specifies the number of the element when the Tab key is used for navigating.

Selector: tab-index

Default Value: 0

The value of this property will be passed to the tabindex attribute of the HTML element that underlies the UI component.

Configures the toolbar.

Selector: DxToolbar

Default Value: undefined

Specifies whether to enable two-way data binding.

Selector: two-way-binding-enabled

Default Value: true

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.

Specifies whether the UI component is visible.

Specifies the UI component's width.

This property accepts a value of one of the following types:

DataGrid does not support the

transform: scale

CSS rule. Specify

height

and width as a percentage instead.

Specifies whether text that does not fit into a column should be wrapped.

Selector: word-wrap-enabled

Default Value: false

DataGrid Demo TreeList Demo

Feel free to share topic-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4