React DataGrid - Customize Cells

For a live example of cell customization, refer to the following demo:

View Demo

Customize the Value and Text

Use the customizeText function to customize the text displayed in cells. Note that this text is not used to sort, filter, and group data or calculate summaries.

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        columns: [{
            dataField: "Price",
            customizeText: function(cellInfo) {
                return cellInfo.value + "$";
            }
        }]
    });
});
Angular
TypeScript
HTML
import { DxDataGridModule } from "devextreme-angular";
// ...
export class AppComponent {
    constructor() {
        // Uncomment the line below if the function should be executed in the component's context
        // this.priceColumn_customizeText = this.priceColumn_customizeText.bind(this);
    }

    priceColumn_customizeText (cellInfo) {
        return cellInfo.value + "$";
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
<dx-data-grid ... >
    <dxi-data-grid-column dataField="Price" [customizeText]="priceColumn_customizeText"></dxi-data-grid-column>
</dx-data-grid>
Vue
App.vue
<template>
    <DxDataGrid ... >
        <DxColumn
            data-field="Price"
            :customize-text="priceColumn_customizeText"
        />
    </DxDataGrid>
</template>

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

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

export default {
    components: {
        DxDataGrid,
        DxColumn
    },
    methods: {
        priceColumn_customizeText(cellInfo) {
            return cellInfo.value + '$';
        }
    }
}
</script>
React
App.js
import React from 'react';

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

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

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

        // Uncomment the line below if the function should be executed in the component's context
        // this.priceColumn_customizeText = this.priceColumn_customizeText.bind(this);
    }

    priceColumn_customizeText(cellInfo) {
        return cellInfo.value + '$';
    }

    render() {
        return (
            <DataGrid ... >
                <Column
                    dataField="Price"
                    customizeText={priceColumn_customizeText}
                />
            </DataGrid>
        );
    }
}
export default App;

To use the text displayed in cells in those data processing operations, specify the calculateCellValue function instead. It populates a column with custom values and allows you to create unbound columns - columns that are not bound to any individual data field. In the following example, this function combines full names using data from the firstName and lastName fields:

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        columns: [{
            caption: "Full Name",
            calculateCellValue: function (rowData) {
                return rowData.firstName + " " + rowData.lastName;
            }
        }]
    });
});
Angular
TypeScript
HTML
import { DxDataGridModule } from "devextreme-angular";
// ...
export class AppComponent {
    constructor() {
        // Uncomment the line below if the function should be executed in the component's context
        // this.fullNameColumn_calculateCellValue = this.fullNameColumn_calculateCellValue.bind(this);
    }

    fullNameColumn_calculateCellValue (rowData) {
        return rowData.firstName + " " + rowData.lastName;
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
<dx-data-grid ... >
    <dxi-data-grid-column caption="Full Name" [calculateCellValue]="fullNameColumn_calculateCellValue"></dxi-data-grid-column>
</dx-data-grid>
Vue
App.vue
<template>
    <DxDataGrid ... >
        <DxColumn
            caption="Full Name"
            :calculate-cell-value="fullNameColumn_calculateCellValue"
        />
    </DxDataGrid>
</template>

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

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

export default {
    components: {
        DxDataGrid,
        DxColumn
    },
    methods: {
        fullNameColumn_calculateCellValue(rowData) {
            return rowData.firstName + ' ' + rowData.lastName;
        }
    }
}
</script>
React
App.js
import React from 'react';

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

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

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

        // Uncomment the line below if the function should be executed in the component's context
        // this.fullNameColumn_calculateCellValue = this.fullNameColumn_calculateCellValue.bind(this);
    }

    fullNameColumn_calculateCellValue(rowData) {
        return rowData.firstName + ' ' + rowData.lastName;
    }

    render() {
        return (
            <DataGrid ... >
                <Column
                    caption="Full Name"
                    calculateCellValue={fullNameColumn_calculateCellValue}
                />
            </DataGrid>
        );
    }
}
export default App;

View Demo

Some features are disabled in columns with calculated values. Refer to the calculateCellValue description for a list of disabled features and the properties that enable them.

Customize Cell Appearance

Apply a Style to All Cells in a Column

You can use CSS rules and assign a class to the columns.cssClass property to apply styles to all the cells in a column.

Apply a Style to Individual Cells or Rows (Conditional Formatting)

Implement the onCellPrepared function. It allows you to customize the entire cell's markup after the layout is generated.

The following example demonstrates how to use the onCellPrepared function to conditionally change the cell color. As a result, the DataGrid component paints the cells red where the speed exceeds the speed limit.

Remove the e.column.dataField === "Speed" condition to apply the appearance to all the cells in a row.

Change Color Conditionally with onCellPrepared

jQuery
index.js
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        onCellPrepared: function(e) {
            if (e.rowType === "data") {
                if (e.column.dataField === "Speed" && e.data.Speed > e.data.SpeedLimit) {
                    e.cellElement.css({"color":"white", "background-color":"red"});
                    // or
                    e.cellElement.addClass("my-class");
                }
            }
        }
    });
});
Angular
app.component.html
app.component.ts
<dx-data-grid
    (onCellPrepared)="onCellPrepared($event)">
</dx-data-grid>
// ...
export class AppComponent {
    onCellPrepared (e) {
        if (e.rowType === "data") {
            if (e.column.dataField === "Speed" && e.data.Speed > e.data.SpeedLimit) {
                e.cellElement.style.cssText = "color: white; background-color: red";
                // or
                e.cellElement.classList.add("my-class");
            }
        }
    }
}
Vue
App.vue
<template>
    <DxDataGrid ...
        @cell-prepared="onCellPrepared">
    </DxDataGrid>
</template>

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

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

export default {
    components: {
        DxDataGrid
    },
    methods: {
        onCellPrepared(e) {
            if (e.rowType === "data") {
                if (e.column.dataField === "Speed" && e.data.Speed > e.data.SpeedLimit) {
                    e.cellElement.style.cssText = "color: white; background-color: red";
                    // or
                    e.cellElement.classList.add("my-class");
                }
            }
        }
    }
}
</script>
React
App.js
import React from 'react';

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

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

const cellPrepared = (e) => {
    if (e.rowType === "data") {
        if (e.column.dataField === "Speed" && e.data.Speed > e.data.SpeedLimit) {
            e.cellElement.style.cssText = "color: white; background-color: red";
            // or
            e.cellElement.classList.add("my-class");
        }
    }
}

function App() {
    return (
        <DataGrid ...
            onCellPrepared={cellPrepared}>
        </DataGrid>
    );
}

export default App;

You can also specify the columns.cellTemplate property. It allows you to replace cell content with custom markup, but does not give you access to the entire cell element.

The example below shows how to use the columns.cellTemplate property to implement the same functionality.

Change Color Conditionally with cellTemplate

jQuery
index.js
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        columns: [{
            dataField: 'Speed',
            cellTemplate: function(container, cellInfo) {
                const valueDiv = $("<div>").text(cellInfo.value);
                if (cellInfo.data.Speed > cellInfo.data.SpeedLimit) {
                    valueDiv.css({"color":"white", "background-color":"red"});
                }
                return valueDiv;
            }
        }]
    });
});
Angular
app.component.html
app.component.css
<dx-data-grid ... >
    <dxi-data-grid-column
        dataField="Speed"
        cellTemplate="limitTemplate"
    ></dxi-data-grid-column>
    <div *dxTemplate="let cellInfo of 'limitTemplate'">
        <div [ngClass]="{'my-class': cellInfo.data.Speed > cellInfo.data.SpeedLimit}">
            {{cellInfo.value}}
        </div>                                                 
    </div>
</dx-data-grid>
.my-class {
    background-color: red;
    color: white;
}
Vue
App.vue
<template>
    <DxDataGrid ... >
        <DxColumn
            data-field="Speed"
            cell-template="grid-cell"
        />
        <template #grid-cell="{ data }">
            <div
                :class="{
                    'my-class': cellInfo.data.Speed > cellInfo.data.SpeedLimit,
                }"
            >{{data.value}}</div>
        </template>
    </DxDataGrid>
</template>

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

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

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

<style>
    .my-class {
        background-color: red;
        color: white;
    }
</style>
React
App.js
index.css
import React from 'react';

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

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

const renderGridCell = (data) => {
    let className = '';
    if (cellInfo.data.Speed > cellInfo.data.SpeedLimit) {
        className += 'my-class';
    }
    return <div className={className}>{cellInfo.value}</div>;
}

function App() {
    return (
        <DataGrid ... >
            <Column
                dataField="Speed"
                cellRender={renderGridCell}
            />
        </DataGrid>
    );
}
export default App;
.my-class {
    background-color: red;
    color: white;
}

If the changes are not applied immediately, use the repaint() method to repaint DataGrid or the repaintRows(rowIndexes) method to repaint specific rows only.

View Demo

See Also

Customize Row Appearance

Change Style Based on Row State (Selected, Focused, Hovered)

To change row selection color, use the following CSS rules:

Selected
.dx-datagrid-rowsview .dx-selection.dx-row:not(.dx-row-focused):not(.dx-row-removed) > td {
    background-color: red;
    color: unset;
}

Set the focusedRowEnabled and/or hoverStateEnabled properties to true to enable focused row and hover features. Specify the following CSS rules to change row color:

Focused
Hovered
.dx-datagrid-rowsview .dx-row-focused.dx-data-row .dx-command-edit:not(.dx-focused) .dx-link,
.dx-datagrid-rowsview .dx-row-focused.dx-data-row > td:not(.dx-focused),
.dx-datagrid-rowsview .dx-row-focused.dx-data-row > tr > td:not(.dx-focused) {
    background-color: red !important;
    color: #fff !important; 
}
.dx-data-row.dx-state-hover:not(.dx-selection):not(.dx-row-inserted):not(.dx-row-removed):not(.dx-edit-row) > td:not(.dx-focused) {  
    background-color: orange !important;  
    color: unset !important;  
}  

Change Style Based on Row Data (Conditional Formatting)

To customize the existing row appearance, implement the onRowPrepared event handler. This handler allows you to customize the existing row layout after it is generated. If a customization is not immediately applied, use the repaintRows(rowIndexes) method to repaint DataGrid rows.

View Demo

The following example demonstrates how to use the onRowPrepared function to conditionally change the cell color. As a result, the DataGrid component paints the rows red where the speed exceeds the speed limit.

Change Color Conditionally with onRowPrepared

jQuery
index.js
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        onRowPrepared: function(e) {
            if (e.rowType === "data") {
                if (e.data.Speed > e.data.SpeedLimit) {
                    e.rowElement.css({"color":"white", "background-color":"red"});
                    // or
                    e.rowElement.addClass("my-class");
                    // To override alternation color
                    e.rowElement.removeClass("dx-row-alt");
                }
            }
        }
    });
});
Angular
app.component.html
app.component.ts
<dx-data-grid
    (onRowPrepared)="onRowPrepared($event)">
</dx-data-grid>
// ...
export class AppComponent {
    onRowPrepared(e) {
        if (e.rowType === "data") {
            if (e.data.Speed > e.data.SpeedLimit) {
                e.cellElement.style.cssText = "color: white; background-color: red";
                // or
                e.rowElement.classList.add("my-class");
                // To override alternation color
                e.rowElement.className = e.rowElement.className.replace("dx-row-alt", "");
            }
        }
    }
}
Vue
App.vue
<template>
    <DxDataGrid ...
        @row-prepared="onRowPrepared">
    </DxDataGrid>
</template>

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

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

export default {
    components: {
        DxDataGrid
    },
    methods: {
        onRowPrepared(e) {
            if (e.rowType === "data") {
                if (e.data.Speed > e.data.SpeedLimit) {
                    e.cellElement.style.cssText = "color: white; background-color: red";
                    // or
                    e.rowElement.classList.add("my-class");
                    // To override alternation color
                    e.rowElement.className = e.rowElement.className.replace("dx-row-alt", "");
                }
            }
        }
    }
}
</script>
React
App.js
import React from 'react';

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

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

const rowPrepared = (e) => {
    if (e.rowType === "data") {
        if (e.data.Speed > e.data.SpeedLimit) {
            e.cellElement.style.cssText = "color: white; background-color: red";
            // or
            e.rowElement.classList.add("my-class");
            // To override alternation color
            e.rowElement.className = e.rowElement.className.replace("dx-row-alt", "");
        }
    }
}

function App() {
    return (
        <DataGrid ...
            onRowPrepared={rowPrepared}>
        </DataGrid>
    );
}

export default App;

You can also use the dataRowTemplate property to customize row appearance.

Add Tooltips to Cells

The cellHintEnabled property adds a native browser tooltip to truncated cell content automatically. If you use a custom cellTemplate, you need to add the title attribute manually:

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        dataSource: dataSource,
        columns: [{
            dataField: "name",
            caption: "Name"
        }, {
            dataField: "description",
            caption: "Description",
            cellTemplate: function(container, options) {
                $("<div>")
                    .text(options.value)
                    .attr("title", options.value)
                    .appendTo(container);
            }
        }]
    });
});
Angular
app.component.html
app.component.ts
<dx-data-grid [dataSource]="dataSource">
    <dxi-data-grid-column dataField="name" caption="Name"></dxi-data-grid-column>
    <dxi-data-grid-column
        dataField="description"
        caption="Description"
        cellTemplate="descriptionTemplate">
    </dxi-data-grid-column>
    <div *dxTemplate="let cell of 'descriptionTemplate'" [title]="cell.value">
        {{ cell.value }}
    </div>
</dx-data-grid>
import { Component } from "@angular/core";
import { DxDataGridModule } from "devextreme-angular";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    standalone: true,
    imports: [DxDataGridModule]
})
export class AppComponent {
    dataSource = [ /* ... */ ];
}
Vue
App.vue
<template>
    <DxDataGrid :data-source="dataSource">
        <DxColumn data-field="name" caption="Name" />
        <DxColumn
            data-field="description"
            caption="Description"
            cell-template="descriptionTemplate"
        />
        <template #descriptionTemplate="{ data: cell }">
            <div :title="cell.value">{{ cell.value }}</div>
        </template>
    </DxDataGrid>
</template>

<script setup lang="ts">
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';

const dataSource = [ /* ... */ ];
</script>
React
App.tsx
import React from 'react';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DataGrid, Column } from 'devextreme-react/data-grid';

const dataSource = [ /* ... */ ];

function DescriptionCell({ data }: { data: { value: string } }) {
    return <div title={data.value}>{data.value}</div>;
}

export default function App() {
    return (
        <DataGrid dataSource={dataSource}>
            <Column dataField="name" caption="Name" />
            <Column
                dataField="description"
                caption="Description"
                cellRender={(data) => <DescriptionCell data={data} />}
            />
        </DataGrid>
    );
}

To add tooltips to multiple columns without modifying each cell template, use the onCellPrepared event:

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        dataSource: dataSource,
        columns: ["name", "description"],
        onCellPrepared: function(e) {
            if (e.rowType === "data") {
                $(e.cellElement).attr("title", e.value);
            }
        }
    });
});
Angular
app.component.html
app.component.ts
<dx-data-grid
    [dataSource]="dataSource"
    (onCellPrepared)="onCellPrepared($event)">
    <dxi-data-grid-column dataField="name" caption="Name"></dxi-data-grid-column>
    <dxi-data-grid-column dataField="description" caption="Description"></dxi-data-grid-column>
</dx-data-grid>
import { Component } from "@angular/core";
import { DxDataGridModule } from "devextreme-angular";
import { CellPreparedEvent } from "devextreme/ui/data-grid";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    standalone: true,
    imports: [DxDataGridModule]
})
export class AppComponent {
    dataSource = [ /* ... */ ];

    onCellPrepared(e: CellPreparedEvent) {
        if (e.rowType === "data") {
            (e.cellElement as HTMLElement).title = e.value;
        }
    }
}
Vue
App.vue
<template>
    <DxDataGrid
        :data-source="dataSource"
        @cell-prepared="onCellPrepared">
        <DxColumn data-field="name" caption="Name" />
        <DxColumn data-field="description" caption="Description" />
    </DxDataGrid>
</template>

<script setup lang="ts">
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
import type { CellPreparedEvent } from 'devextreme/ui/data-grid';

const dataSource = [ /* ... */ ];

function onCellPrepared(e: CellPreparedEvent) {
    if (e.rowType === 'data') {
        (e.cellElement as HTMLElement).title = e.value;
    }
}
</script>
React
App.tsx
import React, { useCallback } from 'react';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DataGrid, Column } from 'devextreme-react/data-grid';
import type { CellPreparedEvent } from 'devextreme/ui/data-grid';

const dataSource = [ /* ... */ ];

export default function App() {
    const onCellPrepared = useCallback((e: CellPreparedEvent) => {
        if (e.rowType === 'data') {
            (e.cellElement as HTMLElement).title = e.value;
        }
    }, []);

    return (
        <DataGrid dataSource={dataSource} onCellPrepared={onCellPrepared}>
            <Column dataField="name" caption="Name" />
            <Column dataField="description" caption="Description" />
        </DataGrid>
    );
}

To display a styled Tooltip with custom content, initialize the Tooltip component inside cellTemplate:

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        dataSource: dataSource,
        columns: [{
            dataField: "description",
            caption: "Description",
            cellTemplate: function(container, options) {
                const cellEl = $("<span>")
                    .text(options.value)
                    .appendTo(container);

                $("<div>").dxTooltip({
                    target: cellEl,
                    showEvent: "mouseenter",
                    hideEvent: "mouseleave",
                    contentTemplate: function() {
                        return options.value;
                    }
                }).appendTo(container);
            }
        }]
    });
});
Angular
app.component.html
app.component.ts
<dx-data-grid [dataSource]="dataSource">
    <dxi-data-grid-column
        dataField="description"
        caption="Description"
        cellTemplate="descriptionTemplate">
    </dxi-data-grid-column>
    <div *dxTemplate="let cell of 'descriptionTemplate'">
        <span [id]="'cell_' + cell.rowIndex">{{ cell.value }}</span>
        <dx-tooltip
            [target]="'#cell_' + cell.rowIndex"
            showEvent="mouseenter"
            hideEvent="mouseleave">
            <div *dxTemplate="let t of 'content'">{{ cell.value }}</div>
        </dx-tooltip>
    </div>
</dx-data-grid>
import { Component } from "@angular/core";
import { DxDataGridModule, DxTooltipModule } from "devextreme-angular";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    standalone: true,
    imports: [DxDataGridModule, DxTooltipModule]
})
export class AppComponent {
    dataSource = [ /* ... */ ];
}
Vue
App.vue
<template>
    <DxDataGrid :data-source="dataSource">
        <DxColumn
            data-field="description"
            caption="Description"
            cell-template="descriptionTemplate"
        />
        <template #descriptionTemplate="{ data: cell }">
            <div>
                <span :id="'cell_' + cell.rowIndex">{{ cell.value }}</span>
                <DxTooltip
                    :target="'#cell_' + cell.rowIndex"
                    show-event="mouseenter"
                    hide-event="mouseleave">
                    <template #content>{{ cell.value }}</template>
                </DxTooltip>
            </div>
        </template>
    </DxDataGrid>
</template>

<script setup lang="ts">
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DxDataGrid, DxColumn } from 'devextreme-vue/data-grid';
import { DxTooltip } from 'devextreme-vue/tooltip';

const dataSource = [ /* ... */ ];
</script>
React
App.tsx
import React from 'react';
import 'devextreme/dist/css/dx.fluent.blue.light.css';
import { DataGrid, Column } from 'devextreme-react/data-grid';
import { Tooltip } from 'devextreme-react/tooltip';

const dataSource = [ /* ... */ ];

function DescriptionCell({ data }: { data: { value: string; rowIndex: number } }) {
    return (
        <div>
            <span id={`cell_${data.rowIndex}`}>{data.value}</span>
            <Tooltip
                target={`#cell_${data.rowIndex}`}
                showEvent="mouseenter"
                hideEvent="mouseleave">
                {data.value}
            </Tooltip>
        </div>
    );
}

export default function App() {
    return (
        <DataGrid dataSource={dataSource}>
            <Column
                dataField="description"
                caption="Description"
                cellRender={(data) => <DescriptionCell data={data} />}
            />
        </DataGrid>
    );
}

To add a tooltip to a header cell, use the headerCellTemplate property as described above.

You can replace "mouseenter" and "mouseleave" with other events such as "click", "dblclick", "focus", or "blur" to control when the Tooltip is displayed.