添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
谦和的冰棍  ·  RuntimeException ...·  6 月前    · 
苦闷的烤红薯  ·  GitHub - ...·  8 月前    · 

By default, a column is created for each field of a data source object, but in most cases, it is redundant. To specify a set of columns to be created in a grid, assign an array specifying these columns to the columns property. Each grid column is represented in this array by an object containing column settings or by a data source field that this column is bound to. Detailed information on specifying grid columns is given in the Columns Overview article.

Column properties define the behavior and appearance of a grid column. One of the other capabilities allows you to control the sorting of column values using the allowSorting and sortOrder properties, apply a filter to grid records using the allowFiltering and filterOperations properties, and group grid records using the allowGrouping and groupIndex properties. In addition, you can change the visibility and width of a column using corresponding properties.

To get or set a property or several properties for a column at runtime, use the columnOption method with the required arguments.

NOTE
If values in the column are calculated customarily using the calculateCellValue property, they cannot be edited at runtime.
See Also
  • editing
  • Do not disable the allowExporting property if you export the DataGrid with multi-line headers.

    See Also
  • export
  • When grouping is enabled in the UI component, the user can group data by values of any column. To prohibit a particular column from being used for grouping, set the allowGrouping property of this column to false .

    NOTE
    In a column with calculated values , this property is set to false by default.
    See Also
  • Grouping
  • NOTE
    In a column with calculated values , this property is set to false by default.
    See Also
  • sorting
  • Unlike data columns bound to a data field , unbound columns display custom values returned from the calculateCellValue function. The component executes this function multiple times for each record: when records are rendered, when users sort or filter them, and when summaries are computed. To avoid errors and enhance the UI component performance, make sure that properties of the rowData object used in calculation exist and keep calculations inside this function as simple as possible.

    In the following code, the calculateCellValue function is used to create an unbound column that displays a calculated sales amount. Data objects contain the Price and UnitsSold fields used in the calculation:

    jQuery
    index.js
    var products = [{
        ProductID: 1,
        ProductName: "Fabrikam SLR Camera 35\" X358 Blue",
        Price: 168,
        UnitsSold: 4
    // ...
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            dataSource: products,
            columns: [{
                caption: "Sales Amount",
                calculateCellValue: function(rowData) {
                    return rowData.Price * rowData.UnitsSold;
            // ...
    
    Angular
    app.component.html
    app.component.ts
    app.service.ts
    app.module.ts
    <dx-data-grid
        [dataSource]="products">
        <dxi-column
            caption="Sales Amount"
            [calculateCellValue]="calculateSalesAmount">
        </dxi-column>
    </dx-data-grid>
    import { Component } from '@angular/core';
    import { Product, Service } from './app.service';
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    export class AppComponent {
        products: Product[];
        constructor(service: Service) {
            this.products = service.getProducts();
        calculateSalesAmount(rowData) {
            return rowData.Price * rowData.UnitsSold;
    import { Injectable } from '@angular/core';
    export class Product {
        ProductID: number,
        ProductName: string,
        Price: number,
        UnitsSold: number
    let products: Product[] = [{
        ProductID: 1,
        ProductName: "Fabrikam SLR Camera 35\" X358 Blue",
        Price: 168,
        UnitsSold: 4
    // ...
    @Injectable()
    export class Service {
        getProducts(): Product[] {
            return products;
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { DxDataGridModule } from 'devextreme-angular';
    import { Service } from './app.service';
    @NgModule({
        declarations: [
            AppComponent
        imports: [
            BrowserModule,
            DxDataGridModule
        providers: [
            Service
        bootstrap: [AppComponent]
    export class AppModule { }
    App.vue
    data.js
    <template>
        <DxDataGrid
            :data-source="products">
            <DxColumn
                caption="Sales Amount"
                :calculate-cell-value="calculateSalesAmount">
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    import service from './data.js';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            const products = service.getProducts();
            return {
                products
        methods: {
            calculateSalesAmount(rowData) {
                return rowData.Price * rowData.UnitsSold;
    </script>
    const products = [{
        ProductID: 1,
        ProductName: "Fabrikam SLR Camera 35\" X358 Blue",
        Price: 168,
        UnitsSold: 4
    // ...
    export default {
        getProducts() {
            return products;
    
    React
    App.js
    data.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column 
    } from 'devextreme-react/data-grid';
    import service from './data.js';
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.products = service.getProducts();
        calculateSalesAmount(rowData) {
            return rowData.Price * rowData.UnitsSold;
        render() {
            return (
                <DataGrid
                    dataSource={this.products}>
                    <Column
                        caption="Sales Amount"
                        calculateCellValue={this.calculateSalesAmount}
                </DataGrid>
    export default App;
    const products = [{
        ProductID: 1,
        ProductName: "Fabrikam SLR Camera 35\" X358 Blue",
        Price: 168,
        UnitsSold: 4
    // ...
    export default {
        getProducts() {
            return products;
    

    The following features are disabled in an unbound column, but you can enable them as described in this table:

    Feature Action that enables it Editing Implement the setCellValue function and specify the name property instead of dataField. Sorting Set the allowSorting property to true. Filtering Set the allowFiltering property to true. Searching Set the allowSearch property to true. Grouping (DataGrid only) Set the allowGrouping property to true.

    To invoke the default behavior, call the defaultCalculateCellValue function and return its result.

    jQuery
    index.js
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [{
                calculateCellValue: function(rowData) {
                    // ...
                    return this.defaultCalculateCellValue(rowData);
    
    Angular
    app.component.ts
    app.component.html
    import { Component } from '@angular/core';
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    export class AppComponent {
        calculateCellValue(rowData) {
            // ...
            const column = this as any;
            return column.defaultCalculateCellValue(rowData);
    <dx-data-grid ... >
        <dxi-column ...
            [calculateCellValue]="calculateCellValue">
        </dxi-column>
    </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn ...
                :calculate-cell-value="calculateCellValue">
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    // ...
    export default {
        // ...
        data() {
            return {
                calculateCellValue: function(rowData) {
                    // ...
                    const column = this as any;
                    return column.defaultCalculateCellValue(rowData);
    </script>
    React
    App.js
    // ...
    class App extends React.Component {
        calculateCellValue(rowData) {
            // ...
            const column = this as any;
            return column.defaultCalculateCellValue(rowData);
        render() {
            return (
                <DataGrid ... >
                    <Column ...
                        calculateCellValue={this.calculateCellValue}
                </DataGrid>
    export default App;
    NOTE
    The this keyword refers to the column's configuration.
    See Also
  • columns[].customizeText
  • columns[].calculateDisplayValue
  • This property accepts the name of the data source field that provides display values...

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [{
                dataField: "countryID", // provides values for editing
                calculateDisplayValue: "country" // provides display values
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column
            dataField="countryID" <!-- provides values for editing -->
            calculateDisplayValue="country"> <!-- provides display values -->
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid>
            <DxColumn          
                data-field="countryID" <!-- provides values for editing -->
                calculate-display-value="country"> <!-- provides display values -->  
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn 
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn 
        // ...
    </script>  
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    class App extends React.Component {
        // ...
        render() {
            return (
                <DataGrid>
                    <Column 
                        dataField="countryID"  <!-- provides values for editing -->
                        calculateDisplayValue="country"  <!-- provides display values -->  
                </DataGrid>
    export default App;
    ASP.NET MVC Controls
    Razor C#
    Razor VB
    @(Html.DevExtreme().DataGrid()
        .Columns(columns => columns.Add()
            .DataField("CountryID")
            .CalculateDisplayValue("Country")
    @(Html.DevExtreme().DataGrid() _
        .Columns(Sub(columns)
            columns.Add() _
                .DataField("CountryID") _
                .CalculateDisplayValue("Country")
        End Sub)        
    

    ... or a function that combines display values. Specify this function only if all data processing operations are executed on the client.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [{
                dataField: "countryID", // provides values for editing
                calculateDisplayValue: function (rowData) { // combines display values
                    return rowData.capital + " (" + rowData.country + ")";
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column
            dataField="countryID" <!-- provides values for editing -->
            [calculateDisplayValue]="getCountryWithCapital"> <!-- combines display values -->
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        getCountryWithCapital(rowData) {
            return rowData.capital + " (" + rowData.country + ")";
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid>
            <DxColumn       
                data-field="countryID" <!-- provides values for editing -->
                :calculate-display-value="getCountryWithCapital" <!-- combines display values -->
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn 
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn 
        methods: {
            getCountryWithCapital(rowData) {
                return rowData.capital + " (" + rowData.country + ")";
    </script>  
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    class App extends React.Component {
        // ...
        render() {
            return (
                <DataGrid>
                    <Column
                        dataField="countryID" <!-- provides values for editing -->                 
                        calculateDisplayValue={this.getCountryWithCapital} <!-- combines display values -->
                </DataGrid>
        getCountryWithCapital(rowData) {
            return rowData.capital + " (" + rowData.country + ")";
    export default App;
    ASP.NET MVC Controls
    Razor C#
    Razor VB
    @(Html.DevExtreme().DataGrid()
        .Columns(columns => columns.Add()
            .DataField("CountryID")
            .CalculateDisplayValue(new JS("getCountryWithCapital"))
    <script>
        function getCountryWithCapital(rowData) {
            return rowData.capital + " (" + rowData.country + ")";
    </script>
    @(Html.DevExtreme().DataGrid() _
        .Columns(Sub(columns)
            columns.Add() _
                .DataField("CountryID") _
                .CalculateDisplayValue(New JS("getCountryWithCapital"))
        End Sub)        
    <script>
        function getCountryWithCapital(rowData) {
            return rowData.capital + " (" + rowData.country + ")";
    </script>    

    The UI component uses the specified display values in sorting, searching, and grouping (in case of DataGrid).

    Do not use this property to format text in cells. Instead, use the format, customizeText, or cellTemplate property.

    A user input value.
    Contains an array if the selectedFilterOperation is one of the following: "between", "anyof", "noneof".

    selectedFilterOperation:

    String

    | null

    A selected filter operation.

    target:

    String

    A UI element used to filter data.
    Possible values: "filterRow", "headerFilter", "filterBuilder", "search".

    The calculateFilterExpression function should return a filter expression. A basic filter expression has the following format:

    [selector, comparisonOperator, filterValue]
  • selector
    A dataField or function that returns column values. Pass this.calculateCellValue if your column contains calculated values.

  • comparisonOperator
    One of the following operators: "=", "<>", ">", ">=", "<", "<=", "startswith", "endswith", "contains", "notcontains".

  • filterValue
    A user input value. Values from the selector are compared to this value.

  • A filter expression for the "between" operation has a different format:

    [ [selector, ">=", startValue], "and", [selector, "<=", endValue] ]

    The default "between" implementation is inclusive (filter results include the boundary values). In the following code, the calculateFilterExpression function implements an exclusive "between" operation:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                calculateFilterExpression: function (filterValue, selectedFilterOperation, target) {
                    // Override implementation for the "between" filter operation
                    if (selectedFilterOperation === "between" && $.isArray(filterValue)) {
                        const filterExpression = [
                            [this.dataField, ">", filterValue[0]], 
                            "and", 
                            [this.dataField, "<", filterValue[1]]
                        return filterExpression;
                    // Invoke the default implementation for other filter operations
                    if(!this.defaultCalculateFilterExpression) 
                        return [this.dataField, 'contains', filterValue];  
                    return this.defaultCalculateFilterExpression.apply(this, arguments);
                // ...
    
    Angular
    TypeScript
    HTML
    import { DxDataGridModule } from "devextreme-angular";
    import { Column } from 'devextreme/ui/data_grid';
    // ...
    export class AppComponent {
        calculateFilterExpression (this: Column, filterValue, selectedFilterOperation, target) {
            // Override implementation for the "between" filter operation
            if (selectedFilterOperation === "between" && Array.isArray(filterValue)) {
                const filterExpression = [
                    [this.dataField, ">", filterValue[0]], 
                    "and", 
                    [this.dataField, "<", filterValue[1]]
                return filterExpression;
            // Invoke the default implementation for other filter operations
            if(!this.defaultCalculateFilterExpression) 
                return [this.dataField, 'contains', filterValue];  
            return this.defaultCalculateFilterExpression.apply(this, arguments);
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    <dx-data-grid ... >
        <dxi-column ...
            [calculateFilterExpression]="calculateFilterExpression">
        </dxi-column>
    </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid>
            <DxColumn ...
                :calculate-filter-expression="calculateFilterExpression"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            return {
                calculateFilterExpression (filterValue, selectedFilterOperation, target) {
                    // Override implementation for the "between" filter operation
                    if (selectedFilterOperation === "between" && Array.isArray(filterValue)) {
                        const filterExpression = [
                            [this.dataField, ">", filterValue[0]], 
                            "and", 
                            [this.dataField, "<", filterValue[1]]
                        return filterExpression;
                    // Invoke the default implementation for other filter operations
                    if(!this.defaultCalculateFilterExpression) 
                        return [this.dataField, 'contains', filterValue];  
                    return this.defaultCalculateFilterExpression.apply(this, arguments);
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    function calculateFilterExpression (filterValue, selectedFilterOperation, target) {
        // Override implementation for the "between" filter operation
        if (selectedFilterOperation === "between" && Array.isArray(filterValue)) {
            const filterExpression = [
                [this.dataField, ">", filterValue[0]], 
                "and", 
                [this.dataField, "<", filterValue[1]]
            return filterExpression;
        // Invoke the default implementation for other filter operations
        if(!this.defaultCalculateFilterExpression) 
            return [this.dataField, 'contains', filterValue];  
        return this.defaultCalculateFilterExpression.apply(this, arguments);
    export default function App() {
        return (
            <DataGrid>
                <Column ...
                    calculateFilterExpression={calculateFilterExpression}
            </DataGrid>
    

    If you use the search panel, the DataGrid may invoke the calculateFilterExpression function multiple times for lookup columns. The first call is to filter the lookup's data source, and subsequent calls are to filter the DataGrid's data source.

    DataGrid uses "anyof" and "noneof" filter values for headerFilter. If you specify calculateFilterExpression for headerFilter, return an array of filterExpressions:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                calculateFilterExpression(filterValue, selectedFilterOperation, target){
                    if (target == "headerFilter") {
                        // ...
                        let filterExpression = ["myDataField", "contains", customValue];
                        return [filterExpression];
                // ...
    
    Angular
    TypeScript
    HTML
    import { DxDataGridModule } from "devextreme-angular";
    import { Column } from 'devextreme/ui/data_grid';
    // ...
    export class AppComponent {
        calculateFilterExpression(this: Column, filterValue, selectedFilterOperation, target){
            if (target == "headerFilter") {
                // ...
                let filterExpression = ["myDataField", "contains", customValue];
                return [filterExpression];
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    <dx-data-grid ... >
        <dxi-column ...
            [calculateFilterExpression]="calculateFilterExpression">
        </dxi-column>
    </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid>
            <DxColumn ...
                :calculate-filter-expression="calculateFilterExpression"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            return {
                calculateFilterExpression(filterValue, selectedFilterOperation, target){
                    if (target == "headerFilter") {
                        // ...
                        let filterExpression = ["myDataField", "contains", customValue];
                        return [filterExpression];
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    function calculateFilterExpression(filterValue, selectedFilterOperation, target){
        if (target == "headerFilter") {
            // ...
            let filterExpression = ["myDataField", "contains", customValue];
            return [filterExpression];
    export default function App() {
        return (
            <DataGrid>
                <Column ...
                    calculateFilterExpression={calculateFilterExpression}
            </DataGrid>
    
    See Also
  • filterValue
  • columns[].filterValue
  • columns[].selectedFilterOperation
  • columns[].filterValues
  • columns[].filterType
  • columns[].filterOperations
  • This property accepts the name of the data source field that provides values used to group grid records...

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [{
                dataField: "ColumnValues",
                groupIndex: 0,
                calculateGroupValue: "GroupingValues"
    
    Angular
    app.component.html
    app.module.ts
    <dx-data-grid ... >
        <dxi-column
            dataField="ColumnValues"
            [groupIndex]="0"
            calculateGroupValue="GroupingValues">
        </dxi-column>
    </dx-data-grid>
    import { BrowserModule } from '@angular/platform-browser'; 
    import { NgModule } from '@angular/core'; 
    import { AppComponent } from './app.component'; 
    import { DxDataGridModule } from 'devextreme-angular'; 
    @NgModule({ 
        declarations: [ 
            AppComponent 
        imports: [ 
            BrowserModule, 
            DxDataGridModule 
        providers: [ ], 
        bootstrap: [AppComponent] 
    export class AppModule { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="ColumnValues"
                :group-index="0"
                calculate-group-value="GroupingValues" 
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import DataGrid, { Column } from 'devextreme-react/data-grid';
    function App() {
        // ...
        return (
            <DataGrid ...>
                <Column
                    dataField="ColumnValues"
                    groupIndex={0}
                    calculateGroupValue="GroupingValues" 
            </DataGrid>
    export default App();

    ... or a function that creates custom groups. In the code below, calculateGroupValue creates groups like Today, Yesterday, and Earlier:

    jQuery
    JavaScript
    const getDayDifference = (date1, date2) => {
        const timeDiff = Math.abs(date1.getTime() - date2.getTime());
        return Math.ceil(timeDiff / (1000 * 3600 * 24));  
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [
                // ...
                    dataField: "HireDate",
                    dataType: "date",
                    groupIndex: 0,
                    calculateGroupValue: function(rowData) {       
                        const currentHireDate = rowData.HireDate;
                        const today = new Date();
                        today.setHours(0,0,0,0);
                        const dayDifference = getDayDifference(today, currentHireDate);
                        switch (dayDifference) {
                            case 0: return "Today";
                            case 1: return "Yesterday";
                            // ...
                            default: return "Earlier";
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
        <!-- ... -->
        <dxi-column
            dataField="HireDate"
            [groupIndex]="0"
            [calculateGroupValue]="groupByDate"
            dataType="date">
        </dxi-column>
    </dx-data-grid>
    const getDayDifference = (date1, date2) => {
        const timeDiff = Math.abs(date1.getTime() - date2.getTime());
        return Math.ceil(timeDiff / (1000 * 3600 * 24));  
    export class AppComponent {
        // ...
        groupByDate(rowData) {         
            const currentHireDate = rowData.HireDate;
            const today = new Date();
            today.setHours(0,0,0,0);
            const dayDifference = getDayDifference(today, currentHireDate);
            switch (dayDifference) {
                case 0: return "Today";
                case 1: return "Yesterday";
                // ...
                default: return "Earlier";
    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 { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="HireDate"
                data-type="date"
                :group-index="0"
                :calculate-group-value="groupByDate"
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    const getDayDifference = (date1, date2) => {
        const timeDiff = Math.abs(date1.getTime() - date2.getTime());
        return Math.ceil(timeDiff / (1000 * 3600 * 24));  
    export default {
        components: {
            DxDataGrid,
            DxColumn
        methods: {
            groupByDate(rowData) {               
                const currentHireDate = rowData.HireDate;
                const today = new Date();
                today.setHours(0,0,0,0);
                const dayDifference = getDayDifference(today, currentHireDate);
                switch (dayDifference) {
                    case 0: return "Today";
                    case 1: return "Yesterday";
                    // ...
                    default: return "Earlier";
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import DataGrid, { Column } from 'devextreme-react/data-grid';
    const getDayDifference = (date1, date2) => {
        const timeDiff = Math.abs(date1.getTime() - date2.getTime());
        return Math.ceil(timeDiff / (1000 * 3600 * 24));  
    function App() {
        // ...
        const groupByDate = (rowData) => {          
            const currentHireDate = rowData.HireDate;
            const today = new Date();
            today.setHours(0,0,0,0);
            const dayDifference = getDayDifference(today, currentHireDate);
            switch (dayDifference) {
                case 0: return "Today";
                case 1: return "Yesterday";
                // ...
                default: return "Earlier";
        return (
            <DataGrid ...>
                <Column
                    dataField="HireDate"
                    dataType="date"
                    groupIndex={0}
                    calculateGroupValue={groupByDate}
            </DataGrid>
    export default App;
    NOTE
    This property only accepts strings if remote operations are enabled.

    Group captions and appearance can be customized. To do this, define the groupCellTemplate.

    calculateGroupValue is also used to sort groups when grid records are grouped by this column.

    NOTE
    The this keyword refers to the column's configuration.

    This property accepts the name of the data source field that provides values used to sort this column.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            columns: [{
                dataField: "Position", // provides column values 
                calculateSortValue: "isOnVacation" // provides values used to sort the Position column
    
    Angular
    app.component.html
    app.module.ts
    <dx-data-grid ... >
        <dxi-column
            dataField="Position" <!-- provides column values -->
            calculateSortValue="isOnVacation"> <!-- provides values used to sort the Position column -->
        </dxi-column>
    </dx-data-grid>
    import { BrowserModule } from '@angular/platform-browser'; 
    import { NgModule } from '@angular/core'; 
    import { AppComponent } from './app.component'; 
    import { DxDataGridModule } from 'devextreme-angular'; 
    @NgModule({ 
        declarations: [ 
            AppComponent 
        imports: [ 
            BrowserModule, 
            DxDataGridModule 
        providers: [ ], 
        bootstrap: [AppComponent] 
    export class AppModule { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="Position" <!-- provides column values -->
                calculate-sort-value="isOnVacation" <!-- provides values used to sort the Position column -->
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import DataGrid, { Column } from 'devextreme-react/data-grid';
    function App() {
        // ...
        return (
            <DataGrid ...>
                <Column
                    dataField="Position" // provides column values
                    calculateSortValue="isOnVacation" // provides values used to sort the Position column
            </DataGrid>
    export default App;

    ... or a function that returns such values. In the code below, calculateSortValue concatenates the State and City column values to sort the Employee column:

    jQuery
    JavaScript
    $(function() {
        var dataGrid = $("#dataGridContainer").dxDataGrid({
            columns: [{
                dataField: "Employee",
                sortOrder: "asc",
                calculateSortValue: function (rowData) {
                    return rowData.State + rowData.City;
        }).dxDataGrid("instance");
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
        <dxi-column
            dataField="Employee"
            sortOrder="asc"
            [calculateSortValue]="sortByLocation">
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        sortByLocation (rowData) {
            return rowData.State + rowData.City;
    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 { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="Employee"
                :calculate-sort-value="sortByLocation"
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            return {
                // ...
                sortByLocation(rowData) {
                    return rowData.State + rowData.City;
    </script>
    React
    App.js
    import React from 'react';
    import DataGrid, { Column } from 'devextreme-react/data-grid';
    function sortByLocation(rowData){
        return rowData.State + rowData.City;
    function App() {
        // ...
        return (
            <DataGrid ...>
                <Column
                    dataField="Employee"
                    calculateSortValue={sortByLocation}
            </DataGrid>
    export default App;

    calculateSortValue does not affect group rows. To sort them, implement calculateGroupValue in addition to calculateSortValue. You should also define the groupCellTemplate to apply a custom template for group rows.

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

  • getter(data): Function
    A function that returns the variable that should be tracked.

  • handler(newValue): Function
    A function called when this variable changes.

  • If you implement two-way data binding in your template, set twoWayBindingEnabled to false to switch off the built-in implementation of this feature.

  • In fixed columns, the template is initialized and rendered twice for each cell.

  • Template values have no effect on data operations. Implement the column's calculateCellValue or calculateDisplayValue option to transform the cell's underlying value.

  • jQuery

    The code snippet below uses the watch function. You can test the snippet in the Real-Time Updates demo.

    Note the following:

  • You cannot call watch in a cell in which you want to track data.
  • The data in the cell where watch is called should remain constant.
  • cellTemplate(container, info) { const getter = (data) => data.Amount; const handler = (newValue) => { container.css('background-color', newValue < 100000 ? 'red' : 'green'); info.watch(getter, handler); return $('<div>').text(info.data.ProductName);

    Unlike normal columns, band columns do not hold data. Instead, they collect two or more columns under one column header. To set up this layout, declare the band column using a hierarchical structure. For this, assign the nested columns to the columns field of the band column. For example, the following code declares the "Address" band column and nests three columns within it.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                caption: "Address",
                columns: ["City", "Street", "Apartment"]
                // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column caption="Address">
            <dxi-column dataField="City"></dxi-column>
            <dxi-column dataField="Street"></dxi-column>
            <dxi-column dataField="Apartment"></dxi-column>
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn caption="Address">
                <DxColumn data-field="City" />
                <DxColumn data-field="Street" />
                <DxColumn data-field="Apartment" />
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column caption="Address">
                    <Column dataField="City" />
                    <Column dataField="Street" />
                    <Column dataField="Apartment" />
                </Column>
            </DataGrid>
    

    A nested column has almost every property a regular column has. These properties are described in the columns section of the Reference.

    NOTE
    There is an exception though: nested columns cannot be fixed alone, therefore specifying the fixed and fixedPosition properties for them is useless. However, the whole band column can be fixed as usual.

    For example, the following code specifies the width and sortOrder properties of the "Street" column nested within the fixed "Address" band column.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                caption: "Address",
                fixed: true,
                fixedPosition: "right",
                columns: [
                    "City", {
                        dataField: "Street",
                        width: 100,
                        sortOrder: "asc"
                    "Apartment"
                // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column
            caption="Address"
            [fixed]="true"
            fixedPosition="right">
            <dxi-column dataField="City"></dxi-column>
            <dxi-column dataField="Street" [width]="100" sortOrder="asc"></dxi-column>
            <dxi-column dataField="Apartment"></dxi-column>
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                caption="Address"
                :fixed="true"
                fixed-position="right">
                <DxColumn data-field="City" />
                <DxColumn data-field="Street" :width="100" sort-order="asc" />
                <DxColumn data-field="Apartment" />
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column
                    caption="Address"
                    fixed={true}
                    fixedPosition="right">
                    <Column dataField="City" />
                    <Column dataField="Street" width={100} sortOrder="asc" />
                    <Column dataField="Apartment" />
                </Column>
            </DataGrid>
    

    Band columns support hierarchies of any nesting level. It means that the following structure is acceptable.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                caption: "A",
                columns: [ "A1", "A2", {
                    caption: "A3",
                    columns: ["A31", "A32", {
                        caption: "A33",
                        columns: ["A331", "A332", "A333"]
                caption: "B",
                columns: // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column caption="A">
            <dxi-column dataField="A1"></dxi-column>
            <dxi-column dataField="A2"></dxi-column>
            <dxi-column caption="A3">
                <dxi-column dataField="A31"></dxi-column>
                <dxi-column dataField="A32"></dxi-column>
                <dxi-column caption="A33">
                    <dxi-column dataField="A331"></dxi-column>
                    <dxi-column dataField="A332"></dxi-column>
                    <dxi-column dataField="A333"></dxi-column>
                </dxi-column>
            </dxi-column>
        </dxi-column>
        <dxi-column caption="B">
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn caption="A">
                <DxColumn data-field="A1" />
                <DxColumn data-field="A2" />
                <DxColumn caption="A3">
                    <DxColumn data-field="A31" />
                    <DxColumn data-field="A32" />
                    <DxColumn caption="A33">
                        <DxColumn data-field="A331" />
                        <DxColumn data-field="A332" />
                        <DxColumn data-field="A333" />
                    </DxColumn>
                </DxColumn>
            </DxColumn>
            <DxColumn caption="B">
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column caption="A">
                    <Column dataField="A1" />
                    <Column dataField="A2" />
                    <Column caption="A3">
                        <Column dataField="A31" />
                        <Column dataField="A32" />
                        <Column caption="A33">
                            <Column dataField="A331" />
                            <Column dataField="A332" />
                            <Column dataField="A333" />
                        </Column>
                    </Column>
                </Column>
                <Column caption="B">
                </Column>
            </DataGrid>
    

    Band columns have the isBand flag. Banded columns have the ownerBand property set. Use these properties to distinguish band and banded columns from regular ones in code.

    See Also
  • Band Columns
  • Column Fixing
  • In the following code, this property is assigned a cell-highlighted CSS class that customizes the position column's cell and header styles:

    jQuery
    index.js
    styles.css
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            dataSource: [{
                ID: 1,
                position: "CTO"
            }, // ...
            columns: [ "ID", {
                dataField: "position",
                cssClass: "cell-highlighted"
    .dx-data-row .cell-highlighted {
        background-color: #e6e6e6;
    .dx-header-row .cell-highlighted {
        color: gray;
        font-style: italic;
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    app.component.css
    <dx-data-grid ...
        [dataSource]="employees">
        <dxi-column dataField="ID"></dxi-column>
        <dxi-column dataField="position" cssClass="cell-highlighted"></dxi-column>
    </dx-data-grid>
    import { Component } from '@angular/core';
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    export class AppComponent {
        employees = [{
            ID: 1,
            position: "CTO"
        }, // ...
    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 { }
    ::ng-deep .dx-data-row .cell-highlighted {
        background-color: #e6e6e6;
    ::ng-deep .dx-header-row .cell-highlighted {
        color: gray;
        font-style: italic;
    
    App.vue
    <template>
        <DxDataGrid ...
            :data-source="employees">
            <DxColumn data-field="ID" />
            <DxColumn data-field="position" css-class="cell-highlighted" />
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    const employees = [{
        ID: 1,
        position: "CTO"
    }, // ...
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            employees
    </script>
    <style>
    .dx-data-row .cell-highlighted {
        background-color: #e6e6e6;
    .dx-header-row .cell-highlighted {
        color: gray;
        font-style: italic;
    </style>
    React
    App.js
    styles.css
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import { DataGrid, Column } from 'devextreme-react/data-grid';
    const employees = [{
        ID: 1,
        position: "CTO"
    }, // ...
    class App extends React.Component {
        constructor(props) {
            super(props);
        render() {
            return (
                <DataGrid ...
                    dataSource={employees}>
                    <Column dataField="ID" />
                    <Column dataField="position" cssClass="cell-highlighted" />
                </DataGrid>
    export default App;
    .dx-data-row .cell-highlighted {
        background-color: #e6e6e6;
    .dx-header-row .cell-highlighted {
        color: gray;
        font-style: italic;
    
    ASP.NET MVC Controls
    Razor C#
    styles.css
    @(Html.DevExtreme().DataGrid()
        .DataSource(new JS("employees"))
        .Columns(c => {
            c.Add().DataField("ID");
            c.Add().DataField("position").CssClass("cell-highlighted");
    <script type="text/javascript">
        var employees = [{
            ID: 1,
            position: "CTO"
        }, // ...
    </script>
    .dx-data-row .cell-highlighted {
        background-color: #e6e6e6;
    .dx-header-row .cell-highlighted {
        color: gray;
        font-style: italic;
    

    Indicates how header filter values were combined into groups. Available if target is "headerFilter".
    See the headerFilter.groupInterval property's description for possible values.

    dataField: "Temperature", customizeText: function(cellInfo) { return cellInfo.value + " &deg;C";
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
       <dxi-column
           dataField="Temperature"
           [customizeText]="customizeText"
       ></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 {
        customizeText(cellInfo) {
            return cellInfo.value + " &deg;C";
    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 { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="Temperature" 
                :customize-text="customizeText"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import { DxDataGrid, DxColumn } from "devextreme-vue/data-grid";
    export default {
        components: {
            DxDataGrid,
            DxColumn
        methods: {
            customizeText(cellInfo) {
                return cellInfo.value + " &deg;C";
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, { Column } from "devextreme-react/data-grid";
    class App extends React.Component {
        customizeText = (cellInfo) => {
            return cellInfo.value + " &deg;C";
        render() {
            return (
                <DataGrid ... >
                    <Column dataField="Temperature" customizeText={this.customizeText} />
                </DataGrid>
    export default App;
    ASP.NET MVC Controls
    Razor C#
    @(Html.DevExtreme().DataGrid()
        //...
        .Columns(columns => {
            columns.Add().DataField("Temperature")
                .CustomizeText("customizeText");
    <script type="text/javascript">
        function customizeText(cellInfo) {
            return cellInfo.value + " &deg;C";
    </script>
    NOTE
    The component does not use the specified text to sort, filter, and group data or calculate summaries. If you want to implement described functionality, specify the calculateCellValue function.

    You can call the customizeText function to highlight the matching text correctly when the data displayed in the column matches the search condition.

    See Also
  • Customize the Value and Text
  • columns[].calculateCellValue
  • The columns array can contain column objects and data field names as strings. If you use column objects, specify the dataField property to bind the object to a column from a data source:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [
                "CustomerID",
                { dataField: "EmployeeID", width: 200 },
                "OrderDate",
                { dataField: "Freight", format: "fixedPoint" },
                "ShipName",
                "ShipCity"
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column dataField="CustomerID"></dxi-column>
        <dxi-column dataField="EmployeeID" [width]="200"></dxi-column>
        <dxi-column dataField="OrderDate"></dxi-column>
        <dxi-column dataField="Freight" format="fixedPoint"></dxi-column>
        <dxi-column dataField="ShipName"></dxi-column>
        <dxi-column dataField="ShipCity"></dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn data-field="CustomerID" />
            <DxColumn data-field="EmployeeID" :width="200" />
            <DxColumn data-field="OrderDate" />
            <DxColumn data-field="Freight" format="fixedPoint" />
            <DxColumn data-field="ShipName" />
            <DxColumn data-field="ShipCity" />
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column dataField="CustomerID" />
                <Column dataField="EmployeeID" width={200} />
                <Column dataField="OrderDate" />
                <Column dataField="Freight" format="fixedPoint" />
                <Column dataField="ShipName" />
                <Column dataField="ShipCity" />
            </DataGrid>
    

    Review the following notes about data binding:

  • If you create an unbound column (use the calculateCellValue function), specify the columns[].name property instead of dataField.

  • Data field names cannot be equal to this and should not contain the following characters: ., :, [, and ].

  • Column caption is generated from the dataField value. If you want to use a custom caption, specify it in the caption property. Unlike dataField, caption can contain any characters.

  • If a data field provides values of one data type, but the UI component should cast them to another, specify the proper type in this property. In the following code, values of the ID and hireDate fields are cast to numeric and date data types, respectively.

    jQuery
    JavaScript
    $(function() {
        $("#dataGrid").dxDataGrid({
            // ...
            dataSource: [{
                ID: "1",
                hireDate: 1491821760000
            }, // ...
            columns: [{
                dataField: "ID",
                dataType: "number"
                dataField: "hireDate",
                dataType: "date"
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ...
        [dataSource]="employees">
        <dxi-column
            dataField="ID"
            dataType="number">
        </dxi-column>
        <dxi-column 
            dataField="hireDate"
            dataType="date">
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from 'devextreme-angular';
    // ...
    export class AppComponent {
        employees = [{
            ID: "1",
            hireDate: 1491821760000
        }, // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule 
        // ...
    
    ASP.NET MVC Controls
    Razor C#
    @(Html.DevExtreme().DataGrid()
        .DataSource(new JS("employees"))
        .Columns(c => {
            c.Add()
                .DataField("ID")
                .DataType(GridColumnDataType.Number);
            c.Add()
                .DataField("hireDate")
                .DataType(GridColumnDataType.Date);
    <script>
        var employees = [{
            ID: "1",
            hireDate: 1491821760000
        }, // ...
    </script>
    <template>
        <DxDataGrid ...
            :data-source="employees">
            <DxColumn
                data-field="ID"
                data-type="number"
            <DxColumn
                data-field="hireDate"
                data-type="date"
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    const employees = [{
        ID: '1',
        hireDate: 1491821760000
    }, // ...
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            employees
    </script>
    React
    import React from 'react';
    import { DataGrid, Column } from 'devextreme-react/data-grid';
    const employees = [{
        ID: '1',
        hireDate: 1491821760000
    }, // ...
    class App extends React.Component {
        render() {
            return (
                <DataGrid ...
                    dataSource={employees}>
                    <Column dataField="ID" dataType="number" />
                    <Column dataField="hireDate" dataType="date" />
                </DataGrid>
    export default App;
    See Also
  • Troubleshooting - Date String Handling Issues
  • Data Columns
  • The index of the row the cell belongs to. Begins with 0 on each page. Group rows are included.
    Refer to the Column and Row Indexes topic for more information on row indexes.

    A method called to change cell values; optionally, you can also call it to change the displayed value after the editor's value is changed.
    See an example in the Custom Editors demo.

    NOTE
    In batch editing mode, confirm that the value is changed before calling this method to ensure correct cell highlighting.

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

  • getter(data): Function
    A function that returns the variable that should be tracked.

  • handler(newValue): Function
    A function that is called when the variable changes.

  • columns[].editorOptions
    Use it to specify default editor properties (except onValueChanged).

  • onEditorPreparing
    Use it to:

  • Change the editor's type.
  • Override the default editor's onValueChanged handler.
  • Dynamically change editor properties in the editing state.
  • Implement other customization cases.
  • Please review the following notes:

  • If you implement two-way data binding in your template, set twoWayBindingEnabled to false to disable this feature's default implementation.

  • If you specify validationRules, the editCellTemplate must contain a DevExtreme editor to which the DataGrid will apply these rules.

  • If a column is fixed or it is hidden with hidingPriority, the template is initialized and rendered twice for each cell.

  • In this object, you can specify the default UI component's properties (except onValueChanged, which you can specify in onEditorPreparing).

    The default editor UI component depends on the column configuration. The following table illustrates the dependency:

    Column Configuration Default Editor dataType: "date"
    "datetime" DateBox "number" NumberBox "boolean" CheckBox "string"
    "object" TextBox lookup is defined SelectBox
    Angular

    Because of this dependency, editorOptions cannot be typed and are not implemented as nested configuration components. Specify editorOptions with an object.

    app.component.html
    app.module.ts
    <dx-data-grid ... >
        <dxi-column ...
            [editorOptions]="{ format: 'currency', showClearButton: true }">
        </dxi-column>
    </dx-data-grid>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { DxDataGridModule } from 'devextreme-angular';
    @NgModule({
        declarations: [
            AppComponent
        imports: [
            BrowserModule,
            DxDataGridModule
        providers: [ ],
        bootstrap: [AppComponent]
    export class AppModule { }

    Because of this dependency, editorOptions cannot be typed and are not implemented as nested configuration components. Specify editorOptions with an object. We recommend that you declare the object outside the configuration component to prevent possible issues caused by unnecessary re-rendering.

    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn ...
                :editor-options="columnEditorOptions"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        data() {
            return {
                columnEditorOptions: { format: 'currency', showClearButton: true }
    </script>
    React

    Because of this dependency, editorOptions cannot be typed and are not implemented as nested configuration components. Specify editorOptions with an object. We recommend that you declare the object outside the configuration component to prevent possible issues caused by unnecessary re-rendering.

    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    class App extends React.Component {
        columnEditorOptions = { format: 'currency', showClearButton: true };
        render() {
            return (
                <DataGrid ... >
                    <Column ...
                        editorOptions={this.columnEditorOptions}
                </DataGrid>
    export default App;
  • Change the editor type.
  • Override the default editor's onValueChanged handler.
  • Dynamically change editor properties in the editing state.
  • Implement other customization cases.
  • See Also
  • columns[].showEditorAlways
  • When true, HTML tags are displayed as plain text; when false, they are applied to the values of the column. If you disable this property, malicious code can be executed. Refer to the following help topic for more information: Potentially Vulnerable API - encodeHtml.

    When the DataGrid is exported to Excel, HTML tags are always exported as plain text.

    The nested filter builder also allows users to select from an extended set of operations that include "anyof", "noneof", "isblank", "isnotblank", and names of custom operations (if any).

    The filterOperations property can also accept an empty array. In this case, the selectedFilterOperation applies, and users cannot change it.

    See Also
  • columns[].selectedFilterOperation
  • columns[].filterValue
  • include
    Values in the header filter are unselected initially, and a user can select values to apply a filter.
  • exclude
    All values in the header filter are selected initially. A user can deselect values to change the filter.
  • This property changes when the user clicks the Select All checkbox in the header filter (only if header filter displays plain data):

    Select All filterType / filterValues filterType: "include"
    filterValues: null filterType: "exclude"
    filterValues: null
    See Also
  • Filtering API
  • columns[].filterValues
  • When DevExtreme loads the grid, it passes the value of the filterValue property to the selectedFilterOperation method.

    Note: Convert date strings into Date objects before you pass them to the filter expression.

    NOTE
    The filter row and header filter can work simultaneously. If you specify the filterValue property to set up the filter row, it limits the filter values for the header filter and vice versa: if you specify the filterValues property to set up the header filter, it limits the filter row's filter values.

    Note: Convert date strings into Date objects before you pass them to the filter expression.

    If you specify the headerFilter.groupInterval property, each member of the filterValues array indicates the beginning of a value range:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                dataField: "ID",
                dataType: "number",
                headerFilter: { groupInterval: 100 },
                filterValues: [500, 700], // Filter intervals are 500-600 and 700-800
            // ...
    
    Angular
    app.component.html
    app.module.ts
    <dx-data-grid ... >
        <dxi-column
            dataField="ID"
            dataType="number"
            [filterValues]="[500, 700]"> <!-- Filter intervals are 500-600 and 700-800 -->
            <dxo-header-filter
                [groupInterval]="100">
            </dxo-header-filter>
        </dxi-column>
    </dx-data-grid>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { DxDataGridModule } from 'devextreme-angular';
    @NgModule({
        declarations: [
            AppComponent
        imports: [
            BrowserModule,
            DxDataGridModule
        providers: [ ],
        bootstrap: [AppComponent]
    export class AppModule { }
    App.vue
    <template>
        <DxDataGrid>
            <DxColumn
                data-field="ID"
                data-type="number"
                :filter-values="[500, 700]"> <!-- Filter intervals are 500-600 and 700-800 -->
                <DxHeaderFilter
                    :group-interval="100"
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn,
        DxHeaderFilter
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn,
            DxHeaderFilter
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column,
        HeaderFilter
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid>
                <Column
                    dataField="ID"
                    dataType="number"
                    filterValues={[500, 700]}> {/* Filter intervals are 500-600 and 700-800 */}
                    <HeaderFilter
                        groupInterval={100}>
                    </HeaderFilter>
                </Column>
            </DataGrid>
    
    NOTE
    The filter row and header filter can work simultaneously. If you specify the filterValue property to set up the filter row, it limits the filter values for the header filter and vice versa: if you specify the filterValues property to set up the header filter, it limits the filter row's filter values.
    See Also
  • Filtering - Header Filter
  • See the format section for information on accepted values.

    In the following code, the "fixedPoint" format type with a precision of 2 decimal places is applied to column values:

    jQuery
    index.js
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                // ...
                format: {
                    type: "fixedPoint",
                    precision: 2
    
    Angular
    app.component.html
    app.module.ts
    <dx-data-grid ... >
        <dxi-column ... >
            <dxo-format
                type="fixedPoint"
                [precision]="2">
            </dxo-format>
        </dxi-column>
    </dx-data-grid>
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { DxDataGridModule } from 'devextreme-angular';
    @NgModule({
        declarations: [
            AppComponent
        imports: [
            BrowserModule,
            DxDataGridModule
        providers: [ ],
        bootstrap: [AppComponent]
    export class AppModule { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn ... >
                <DxFormat
                    type="fixedPoint"
                    :precision="2"
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn,
        DxFormat
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn,
            DxFormat
        data() {
            // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column,
        Format
    } from 'devextreme-react/data-grid';
    class App extends React.Component {
        // ...
        render() {
            return (
                <DataGrid>
                    <Column ... >
                        <Format
                            type="fixedPoint"
                            precision={2}
                    </Column>
                </DataGrid>
    export default App;

    The format property also limits user input in cells that use the DateBox UI component for editing. For cells that use the NumberBox UI component, you can specify the editorOptions.format property, as shown in the following demo:

    When being exported to Excel, the specified format is converted to an Excel format as follows:

  • Numeric
    Converted to the Number format, except for "largeNumber", which is exported without formatting.

  • Currency
    Converted to the Currency format.

  • Date-Time
    Converted to the Date or Time format, depending on the cell value.
    Exceptions: "quarter" and "quarterAndYear" are exported as Short Date; "minute" and "millisecond" are exported as Long Time.

  • Function
    Cannot be converted automatically. Assign this function to the customizeText property instead of the format property.

  • Custom format string
    Cannot be converted, the cell value is exported without formatting. To export this format, return the formatted string from the customizeText callback as follows:

    jQuery
    index.js
    $(function() {
        $("#gridContainer").dxDataGrid({
            // ...
            columns:[{
                // ...
                format: "0.##",   
                customizeText: (options) => {
                    return options.valueText;
            export: {
                enabled: true
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
        <dxi-column ...
            format="0.##" 
            [customizeText]="customizeText">
        </dxi-column>
        <dxo-export [enabled]="true">
        </dxo-export>
    </dx-data-grid>
    import { Component } from '@angular/core';
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    export class AppComponent {
        customizeText(options) {
            return options.valueText;
    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 { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn ...
                format="0.##"
                :customize-text="customizeText"
            <DxExport
                :enabled="true"
        </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
        methods: {
            customizeText(options) {
                return options.valueText;
    </script>
    React
    App.js
    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 ... >
                    <Column ...
                        format="0.##"
                        customizeText={this.customizeText} 
                    <Export 
                        enabled={true}
                </DataGrid>
        customizeText(options) {
            return options.valueText;
    export default App;
  • A column's default format depends on the data type, which is detected automatically. If you find that a format is exported incorrectly, you will need to explicitly set the column's dataType.

    See Also
  • customizeText
  • Value Formatting
  • In the following code, the Full_Name grid column in the editing state produces a form item that spans two form columns. The item's label is on top of the editor:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            editing: {
                allowUpdating: true,
                mode: "form"
            columns: [{
                dataField: "Full_Name",
                formItem: {
                    colSpan: 2,
                    label: {
                        location: "top"
            // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxo-editing
            [allowUpdating]="true"
            mode="form">
        </dxo-editing>
        <dxi-column dataField="Full_Name">
            <dxo-form-item [colSpan]="2">
                <dxo-label location="top"></dxo-label>
            </dxo-form-item>
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxEditing
                :allow-updating="true"
                mode="form"
            <DxColumn data-field="Full_Name">
                <DxFormItem :col-span="2">
                    <DxLabel location="top" />
                </DxFormItem>
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxEditing,
        DxColumn,
        DxFormItem,
        DxLabel
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxEditing,
            DxColumn,
            DxFormItem,
            DxLabel
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Editing,
        Column,
        FormItem,
        Label
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Editing
                    allowUpdating={true}
                    mode="form"
                <Column dataField="Full_Name">
                    <FormItem colSpan={2}>
                        <Label location="top" />
                    </FormItem>
                </Column>
            </DataGrid>
    
    ASP.NET MVC Controls
    Razor C#
    @(Html.DevExtreme().DataGrid()
        // ...
        .Editing(e => e
            .AllowUpdating(true)
            .Mode(GridEditMode.Form)
        .Columns(cols => {
            // ...
            cols.Add().DataField("Full_Name")
                .FormItem(item => item
                    .ColSpan(2)
                    .Label(l => l.Location(FormLabelLocation.Top)
    
  • The formItem object does not allow you to specify a template. Use the column's editCellTemplate instead.

  • Do not use formItem to override editor's onValueChanged. Implement onEditorPreparing instead.

  • The component does not check validation rules in the formItem object. Use the columns.validationRules property to customize validation instead. For more information, refer to the Data Validation article.

  • key: "Group 1", // The group's name items: [ // Data objects that fall into the group { ... }, { ... }, // ...

    The index of the row the cell belongs to. Begins with 0 on each page. Group rows are included.
    Refer to the Column and Row Indexes topic for more information on row indexes.

  • The caption and the value of the column by which data is grouped

  • groupContinuesMessage and groupContinuedMessage (if the group is spread across two or more pages)

  • The following example shows how to display column value only:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [ 
                    dataField: "Country",
                    groupIndex: 0,
                    groupCellTemplate: function(element, options) {
                        element.text(options.value);
            // ...
    
    Angular
    <dx-data-grid ... > <dxi-column dataField="Country" [groupIndex]="0" groupCellTemplate="groupCellTemplate"> </dxi-column> <div *dxTemplate="let data of 'groupCellTemplate'"> <div>{{data.value}}</div> </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="Country"
                :group-index="0"
                group-cell-template="groupCellTemplate"
            <template #groupCellTemplate="{ data }">
                <div>{{data.value}}</div>
            </template>
        </DxDataGrid>
    </template>
    <script>
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import DataGrid, { Column } from 'devextreme-react/data-grid';
    const GroupCell = options => <div>{options.value}</div>;
    export default function App() {
        // ...
        return (
            <DataGrid ...>
                <Column
                    dataField="Country"
                    defaultGroupIndex={0}
                    groupCellRender={GroupCell}
            </DataGrid>
    

    The following details should be taken into account when you use a groupCellTemplate:

  • When the DataGrid is exported, it omits customizations made in the template. However, you can recreate them in the exported file using the ExcelJS API. To do so, use the customizeCell function.

  • In fixed columns, the template is initialized and rendered twice for each cell.

  • See Also
  • Custom Templates
  • calculateGroupValue
  • At runtime, the user can group grid records using the context menu or the group panel. But there may be cases when grid records must be grouped initially. To do this, assign an integer value to the groupIndex property of those columns that should be used for grouping grid records. For example, consider the following data source.

    JavaScript
    const dataSource = [
        { FirstName: "John", LastName: "Doe", Title: "Sales Manager" },
        { FirstName: "Michael", LastName: "King", Title: "Sales Representative" },
        // ...
    

    To group these records first by the "LastName" field and then by the "FirstName" field, use the following code.

    jQuery
    JavaScript
    $("#dataGridContainer").dxDataGrid({
        // ...
        columns: [
            { dataField: "FirstName", groupIndex: 1 },
            { dataField: "LastName", groupIndex: 0 },
            // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column dataField="FirstName" [groupIndex]="1"></dxi-column>
        <dxi-column dataField="LastName" [groupIndex]="0"></dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="FirstName"
                :group-index="1"
            <DxColumn
                data-field="LastName"
                :group-index="0"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column
                    dataField="FirstName"
                    groupIndex={1}
                <Column
                    dataField="LastName"
                    groupIndex={0}
            </DataGrid>
    

    The hidingPriority is a unique positive integer that ascends from right to left. The default starting point is 0. Columns with low hidingPriority are hidden first.

  • If you specify this property for at least one column, the column hiding feature is enabled and the default hiding priorities are canceled.

  • Fixed columns ignore the hidingPriority and allowHiding properties.

  • Grouped columns ignore this property.

  • Unlike standard columns, band columns do not contain data. Instead, a band column displays two or more columns underneath its header. To create a banded layout, do one of the following:

  • Create nested column configurations.

  • Specify the isBand and ownerBand properties inside the customizeColumns function.

  • The following code uses the isBand and ownerBand properties to display the "City", "Street", and "Apartment" columns under the "Address" band:

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            customizeColumns: function(columns) {
                columns.push({ // Pushes the "Address" band column into the "columns" array
                    caption: "Address",
                    isBand: true
                const addressFields = ["City", "Street", "Apartment"];
                for (let i = 0; i < columns.length-1; i++) {
                    if (addressFields.indexOf(columns[i].dataField) > -1) // If the column belongs to "Address",
                        columns[i].ownerBand = columns.length-1; // assigns "Address" as the owner band column
    
    Angular
    TypeScript
    HTML
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        customizeColumns (columns) {
            columns.push({ // Pushes the "Address" band column into the "columns" array
                caption: "Address",
                isBand: true
            const addressFields = ["City", "Street", "Apartment"];
            for (let i = 0; i < columns.length - 1; i++) {
                if (addressFields.indexOf(columns[i].dataField) > -1) // If the column belongs to "Address",
                    columns[i].ownerBand = columns.length - 1; // assigns "Address" as the owner band column
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    <dx-data-grid ...
        [customizeColumns]="customizeColumns">
    </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid ...
            :customize-columns="customizeColumns">
            <!-- ... -->
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        // ...
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            // ...
        // ...
        methods: {
            customizeColumns (columns) {
                columns.push({ // Pushes the "Address" band column into the "columns" array
                    caption: "Address",
                    isBand: true
                const addressFields = ["City", "Street", "Apartment"];
                for (let i = 0; i < columns.length - 1; i++) {
                    if (addressFields.indexOf(columns[i].dataField) > -1) // If the column belongs to "Address",
                        columns[i].ownerBand = columns.length - 1; // assigns "Address" as the owner band column
    </script>
    React
    App.js
    import React, { useCallback } from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        // ...
    } from 'devextreme-react/data-grid';
    export default function App() {
        const customizeColumns = useCallback((columns) => {
            columns.push({ // Pushes the "Address" band column into the "columns" array
                caption: "Address",
                isBand: true
            const addressFields = ["City", "Street", "Apartment"];
            for (let i = 0; i < columns.length - 1; i++) {
                if (addressFields.indexOf(columns[i].dataField) > -1) // If the column belongs to "Address",
                    columns[i].ownerBand = columns.length - 1; // assigns "Address" as the owner band column
        }, []);
        return (
            <DataGrid ...
                customizeColumns={customizeColumns}>
                {/* ... */}
            </DataGrid>
    

    Band columns can have the following properties only:

  • alignment
  • allowHiding
  • allowReordering
  • caption
  • columns
  • cssClass
  • fixed
  • fixedPosition
  • headerCellTemplate
  • ownerBand
  • showInColumnChooser
  • visible
  • visibleIndex
  • NOTE
    Band columns cannot nest command columns.
    See Also
  • Band Columns
  • A lookup column restricts the set of values that can be chosen when a user edits or filters the column. In a lookup column, each cell is a drop-down menu. You can use a lookup column when you need to substitute displayed values with required values. For example, consider that you have two arrays of objects: drivers and buses.

    JavaScript
    const drivers = [
        { driverID: 1, firstName: "John", lastName: "Smith", busID: 2 },
        { driverID: 2, firstName: "Lizzy", lastName: "Cook", busID: 1 },
        { driverID: 3, firstName: "Brian", lastName: "Hawkins", busID: 3 }
    const buses = [
        { busID: 1, plates: "123456" },
        { busID: 2, plates: "AB-1234" },
        { busID: 3, plates: "CD-9876" }
    

    All drivers have the busID field, which refers to a bus. If drivers is the main dataSource, the Bus ID column displays bus IDs, which provides little information to a user. It will be more useful to display bus license plates instead of IDs. For this, the buses array must be set as a lookup dataSource for the Bus ID column. Then, the names of data fields must be assigned to the valueExpr and displayExpr properties. Values from the valueExpr data field will be replaced with values from the displayExpr data field.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            dataSource: drivers,
            // ...
            columns: [{
                dataField: "busID",
                lookup: {
                    dataSource: buses,
                    valueExpr: "busID",
                    displayExpr: "plates"
    
    Angular
    HTML
    TypeScript
    <dx-data-grid [dataSource]="drivers">
        <dxi-column dataField="busID">
            <dxo-lookup
                [dataSource]="buses"
                valueExpr="busID"
                displayExpr="plates">
            </dxo-lookup>
        </dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        drivers = [
            { driverID: 1, firstName: "John", lastName: "Smith", busID: 2 },
            { driverID: 2, firstName: "Lizzy", lastName: "Cook", busID: 1 },
            { driverID: 3, firstName: "Brian", lastName: "Hawkins", busID: 3 }
        buses = [
            { busID: 1, plates: "123456" },
            { busID: 2, plates: "AB-1234" },
            { busID: 3, plates: "CD-9876" }
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ...
            :data-source="drivers">
            <DxColumn data-field="busID">
                <DxLookup
                    :data-source="buses"
                    value-expr="busID"
                    display-expr="plates"
            </DxColumn>
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn,
        DxLookup
    } from 'devextreme-vue/data-grid';
    const drivers = [
        { driverID: 1, firstName: "John", lastName: "Smith", busID: 2 },
        { driverID: 2, firstName: "Lizzy", lastName: "Cook", busID: 1 },
        { driverID: 3, firstName: "Brian", lastName: "Hawkins", busID: 3 }
    const buses = [
        { busID: 1, plates: "123456" },
        { busID: 2, plates: "AB-1234" },
        { busID: 3, plates: "CD-9876" }
    export default {
        components: {
            DxDataGrid,
            DxColumn,
            DxLookup
        data() {
            return {
                drivers,
                buses
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column,
        Lookup
    } from 'devextreme-react/data-grid';
    const drivers = [
        { driverID: 1, firstName: "John", lastName: "Smith", busID: 2 },
        { driverID: 2, firstName: "Lizzy", lastName: "Cook", busID: 1 },
        { driverID: 3, firstName: "Brian", lastName: "Hawkins", busID: 3 }
    const buses = [
        { busID: 1, plates: "123456" },
        { busID: 2, plates: "AB-1234" },
        { busID: 3, plates: "CD-9876" }
    export default function App() {
        return (
            <DataGrid ...
                dataSource={drivers}>
                <Column dataField="busID">
                    <Lookup
                        dataSource={buses}
                        valueExpr="busID"
                        displayExpr="plates"
                </Column>
            </DataGrid>
    

    With this code, the Bus ID column contains license plates instead of IDs. Moreover, the user can choose a plate number from the drop-down menu when editing cells or applying a filter to this column.

    This function allows you to process user input before it is saved to the data source. It accepts the newData, value, and currentRowData parameters. value is the user input that you should assign to one of the newData fields. Fill the empty newData object with fields whose values should be saved in the current row's data object. You can use the read-only currentRowData parameter to access the current row's data.

    jQuery
    index.js
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [
                "Price",
                    dataField: "Count",
                    dataType: "number",
                    setCellValue: function(newData, value, currentRowData) {
                        newData.Count = value;
                        newData.TotalPrice = currentRowData.Price * value;
                "TotalPrice",
                // ...
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
        <dxi-column dataField="Price"></dxi-column>
        <dxi-column
            dataField="Count"
            dataType="number"
            [setCellValue]="setCellValue">
        </dxi-column>
        <dxi-column dataField="TotalPrice"></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 {
        setCellValue (newData, value, currentRowData) {
            newData.Count = value;
            newData.TotalPrice = currentRowData.Price * value;
    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 { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn data-field="Price" />
            <DxColumn data-field="Count" data-type="number" :set-cell-value="setCellValue" />
            <DxColumn data-field="TotalPrice" />
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
        methods: {
            setCellValue(newData, value, currentRowData) {
                newData.Count = value;
                newData.TotalPrice = currentRowData.Price * value;
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import { DataGrid, Column } from 'devextreme-react/data-grid';
    class App extends React.Component {
        setCellValue(newData, value, currentRowData) {
            newData.Count = value;
            newData.TotalPrice = currentRowData.Price * value;
        render() {
            return (
                <DataGrid ... >
                    <Column dataField="Price" />
                    <Column dataField="Count" dataType="numeric" setCellValue={this.setCellValue}/>
                    <Column dataField="TotalPrice" />
                </DataGrid>
    export default App;
    ASP.NET MVC Controls
    Razor C#
    @(Html.DevExtreme().DataGrid()
        // ...
        .Columns(c => {
            c.Add().DataField("Price");
            c.Add().DataField("Count")
                .DataType(GridColumnDataType.Number)
                .SetCellValue(@<text>
                    function(newData, value, currentRowData) {
                        newData.Count = value;
                        newData.TotalPrice = currentRowData.Price * value;
                </text>);
            c.Add().DataField("TotalPrice");
    

    The setCellValue property forces the component to repaint all items in the edit form. Set repaintChangesOnly to true so the component re-renders only the fields with the changed values.

    To perform asynchronous operations in the setCellValue function, return a promise from it. The following code uses this technique to get the Tax value from the server when the State value is changed:

    jQuery
    index.js
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                dataField: "State",
                setCellValue: function(newData, value, currentRowData) {
                    return getTaxRates(value)
                        .done(function(data) {
                            newData.State = value;
                            newData.Tax = data.Tax;
            "Tax",
            // ...
        function getTaxRates(state) {
            var promise = $.ajax({
                // The URL returns { State: 1, Tax: 10 }
                url: "https://www.mywebsite.com/api/getTaxRates",
                dataType: "json",
                data: { State: state }
            return promise;
    
    Angular
    app.component.html
    app.component.ts
    app.module.ts
    <dx-data-grid ... >
        <dxi-column
            dataField="State"
            [setCellValue]="setCellValue">
        </dxi-column>
        <dxi-column dataField="Tax"></dxi-column>
        <!-- ... -->
    </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(private httpClient: HttpClient) {
            this.setCellValue = this.setCellValue.bind(this);
        setCellValue(newData, value, currentRowData) {
            return this.getTaxRates(value).then((data: any) => {
                newData.State = value;
                newData.Tax = data.Tax;
        getTaxRates(state) {
            const params = new HttpParams().set('State', state);
            return new Promise(async (resolve, reject) => {
                try {
                    const data = await lastValueFrom(this.httpClient.get("https://www.mywebsite.com/api/getTaxRates", { params }));
                    // "data" is { State: 1, Tax: 10 }
                    resolve(data);
                } catch (error) {
                    console.error("Data Loading Error", error);
                    reject("Data Loading Error");
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { HttpClientModule } from '@angular/common/http';
    import { DxDataGridModule } from 'devextreme-angular';
    @NgModule({
        declarations: [
            AppComponent
        imports: [
            BrowserModule,
            HttpClientModule,
            DxDataGridModule
        providers: [ ],
        bootstrap: [AppComponent]
    export class AppModule { }
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn data-field="State" :set-cell-value="setCellValue" />
            <DxColumn data-field="Tax" />
            <!-- ... -->
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
    import 'whatwg-fetch';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
        methods: {
            setCellValue(newData, value, currentRowData) {
                return this.getTaxRates(value).then(data => {
                    newData.State = value;
                    newData.Tax = data.Tax;
            getTaxRates(state) {
                let params = '?' + 'State=' + state;
                return fetch("https://www.mywebsite.com/api/getTaxRates${params}")
                    .toPromise()
                    .then(data => {
                        // "data" is { State: 1, Tax: 10 }
                        return data;
                    .catch(error => { throw "Data Loading Error" });
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import { DataGrid, Column } from 'devextreme-react/data-grid';
    import 'whatwg-fetch';
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.setCellValue = this.setCellValue.bind(this);
        setCellValue(newData, value, currentRowData) {
            return this.getTaxRates(value).then(data => {
                newData.State = value;
                newData.Tax = data.Tax;
        getTaxRates(state) {
            let params = '?' + 'State=' + state;
            return fetch("https://www.mywebsite.com/api/getTaxRates${params}")
                .toPromise()
                .then(data => {
                    // "data" is { State: 1, Tax: 10 }
                    return data;
                .catch(error => { throw "Data Loading Error" });
        render() {
            return (
                <DataGrid ... >
                    <Column dataField="State" setCellValue={this.setCellValue}/>
                    <Column dataField="Tax" />
                    {/* ... */}
                </DataGrid>
    export default App;
    ASP.NET MVC Controls
    Razor C#
    @(Html.DevExtreme().DataGrid()
        // ...
        .Columns(c => {
            c.Add().DataField("State")
                .SetCellValue("setCellValue");
            c.Add().DataField("Tax");
            // ...
    <script type="text/javascript">
        function setCellValue(newData, value, currentRowData) {
            return getTaxRates(value).done(function(data) {
                newData.State = value;
                newData.Tax = data.Tax;
        function getTaxRates(state) {
            var promise = $.ajax({
                // The URL returns { State: 1, Tax: 10 }
                url: "https://www.mywebsite.com/api/getTaxRates",
                dataType: "json",
                data: { State: state }
            return promise;
    </script>

    To invoke the default behavior, call the this.defaultSetCellValue(newData, value) function.

    Set the showEditorAlways property to true to display a column cell value in an editor when a user does not edit data. For example, you can use this functionality to display Boolean data as check boxes instead of the "true/false" strings.

    Behavior of the editor in a cell depends on the component's edit mode:

  • The editing.mode property is set to "cell" or "batch". Users can edit values directly in their cells without switching the component to edit mode.

  • The editing.mode property is set to "row", "form" or "popup". Relevant only for Boolean values. The component displays Boolean values in read-only check boxes. Users should click the Edit button to change cell values.

  • This property has the following specifics:

  • The default value of this property depends on the column's dataType. For Boolean columns, the default value is true; for columns of other types - false.

  • The editCellTemplate has higher priority over the cellTemplate if the showEditorAlways property value is true. Relevant for all data types except Boolean.

  • The cellInfo.setValue function does not work when the showEditorAlways property value is true but you do not switch the component to edit mode.

  • HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column dataField="BirthDate" dataType="date"></dxi-column>
        <dxi-column dataField="OrderDate" dataType="date" showEditorAlways="true"></dxi-column>
        <dxi-column dataField="CheckedState" dataType="boolean" showEditorAlways="false"></dxi-column>
        <dxi-column dataField="AvailabilityState" dataType="boolean" ></dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="BirthDate"
                data-type="date"
            <DxColumn
                data-field="OrderDate"
                data-type="date"
                :show-editor-always="true"
            <DxColumn
                data-field="CheckedState"
                data-type="boolean"
                :show-editor-always="false"
            <DxColumn
                data-field="AvailabilityState"
                data-type="boolean"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column
                    dataField="BirthDate"
                    dataType="date"
                <Column
                    dataField="OrderDate"
                    dataType="date"
                    showEditorAlways={true}
                <Column
                    dataField="CheckedState"
                    dataType="boolean"
                    showEditorAlways={false}
                <Column
                    dataField="AvailabilityState"
                    dataType="boolean"
            </DataGrid>
    
    See Also
  • columns[].editorOptions
  • Displaying a grouping column may be useful if you calculate its grouping values. Consider that you need to group records by a column that contains dates. Grouping by full dates seems inconvenient. It would be smarter to group by months or years instead. For this purpose, you calculate grouping values within the calculateGroupValue function and leave the grouping column visible by setting the showWhenGrouped property to true so that the user can view the full dates.

    This property accepts an integer specifying the index of the column in a collection of columns with applied sorting. For example, consider the following data source that can provide data for three columns.

    JavaScript
    const dataSource = [
        { firstName: "John", lastName: "Doe", title: "Sales Manager" },
        { firstName: "Michael", lastName: "King", title: "Sales Representative" },
        // ...
    

    To sort data first by the "Last Name" and then by the "First Name" column, use the following code. Note that the sortOrder property should also be specified.

    jQuery
    JavaScript
    $(function() {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [
                { dataField: "firstName", sortIndex: 1, sortOrder: "asc" },
                { dataField: "lastName", sortIndex: 0, sortOrder: "asc" },
                // ...
    
    Angular
    HTML
    TypeScript
    <dx-data-grid ... >
        <dxi-column dataField="firstName" [sortIndex]="1" sortOrder="asc"></dxi-column>
        <dxi-column dataField="lastName" [sortIndex]="0" sortOrder="asc"></dxi-column>
    </dx-data-grid>
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        // ...
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="firstName"
                :sort-index="1"
                sort-order="asc"
            <DxColumn
                data-field="lastName"
                :sort-index="0"
                sort-order="asc"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    export default function App() {
        return (
            <DataGrid ... >
                <Column
                    dataField="firstName"
                    sortIndex={1}
                    sortOrder="asc"
                <Column
                    dataField="lastName"
                    sortIndex={0}
                    sortOrder="asc"
            </DataGrid>
    

    You can set the sortIndex property at design time to specify initial sorting, or change this property using the columnOption method to sort at runtime.

    This function accepts two cell values and should return a number indicating their sort order:

  • Less than zero
    value1 goes before value2.
  • value1 and value2 remain unchanged relative to each other.
  • Greater than zero
    value1 goes after value2.
  • The string comparison is culture-insensitive by default. Use the following code to make it culture-sensitive:

    jQuery
    JavaScript
    $(function () {
        $("#dataGridContainer").dxDataGrid({
            // ...
            columns: [{
                dataField: "fieldName",
                sortingMethod: function (value1, value2) {
                    // Handling null values
                    if(!value1 && value2) return -1;
                    if(!value1 && !value2) return 0;
                    if(value1 && !value2) return 1;
                    // Determines whether two strings are equivalent in the current locale
                    return value1.localeCompare(value2);
    
    Angular
    TypeScript
    HTML
    import { DxDataGridModule } from "devextreme-angular";
    // ...
    export class AppComponent {
        sortStringsConsideringCulture (value1, value2) {
            // Handling null values
            if(!value1 && value2) return -1;
            if(!value1 && !value2) return 0;
            if(value1 && !value2) return 1;
            // Determines whether two strings are equivalent in the current locale
            return value1.localeCompare(value2);
    @NgModule({
        imports: [
            // ...
            DxDataGridModule
        // ...
    <dx-data-grid ... >
        <dxi-column
            dataField="fieldName"
            [sortingMethod]="sortStringsConsideringCulture">
        </dxi-column>
    </dx-data-grid>
    App.vue
    <template>
        <DxDataGrid ... >
            <DxColumn
                data-field="fieldName"
                :sorting-method="sortStringsConsideringCulture"
        </DxDataGrid>
    </template>
    <script>
    import 'devextreme/dist/css/dx.light.css';
    import DxDataGrid, {
        DxColumn
    } from 'devextreme-vue/data-grid';
    export default {
        components: {
            DxDataGrid,
            DxColumn
        // ...
        methods: {
            sortStringsConsideringCulture (value1, value2) {
                // Handling null values
                if(!value1 && value2) return -1;
                if(!value1 && !value2) return 0;
                if(value1 && !value2) return 1;
                // Determines whether two strings are equivalent in the current locale
                return value1.localeCompare(value2);
    </script>
    React
    App.js
    import React from 'react';
    import 'devextreme/dist/css/dx.light.css';
    import DataGrid, {
        Column
    } from 'devextreme-react/data-grid';
    function sortStringsConsideringCulture (value1, value2) {
        // Handling null values
        if(!value1 && value2) return -1;
        if(!value1 && !value2) return 0;
        if(value1 && !value2) return 1;
        // Determines whether two strings are equivalent in the current locale
        return value1.localeCompare(value2);
    export default function App() {
        return (
            <DataGrid ... >
                <Column
                    dataField="fieldName"
                    sortingMethod={sortStringsConsideringCulture}
            </DataGrid>
    
    NOTE
    The sortingMethod's value1 and value2 are the values returned from the calculateSortValue function if the latter is specified.

    By default, rows are sorted according to the data source. To sort rows in an ascending or descending order, set the sortOrder property to "asc" or "desc". If you need to sort by multiple columns, specify the sortIndex. Otherwise, each sorted column will get a sort index according to its position in the columns array.

    Visible indexes are normalized after the UI component's creation: the leftmost column is assigned an index of 0; the rightmost column's index becomes equal to the number of visible columns minus 1; other columns get the indexes in between.

    IMPORTANT
    This index is used in column reordering only. Do not confuse it with the visible column index, which is used to manipulate cells by calling methods, such as getCellElement(rowIndex, visibleColumnIndex), editCell(rowIndex, visibleColumnIndex), etc.
    See Also
  • Column Reordering
  • The column's width in pixels.
  • String
    A CSS-accepted column width measurement (for example, "55px", "80%" and "auto") except relative units such as em, ch, vh, etc.

    NOTE
    Fixed columns ignore widths specified as a percentage.
  • DataGrid Demo TreeList Demo

    See Also
  • columnAutoWidth
  • columnWidth
  • width
  • Feel free to share topic-related thoughts here.
    If you have technical questions, please create a support ticket in the DevExpress Support Center. All trademarks or registered trademarks are property of their respective owners. Use of this site constitutes acceptance of the Developer Express Inc Website Terms of Use, Privacy Policy (Updated), and . Use of DevExtreme UI components/libraries constitutes acceptance of the Developer Express Inc End User License Agreement. FAQs: Licensing | DevExpress Support Services | Supported Versions & Requirements | Maintenance Releases