DevExtreme React - Templates

Templates allow you to customize DevExtreme UI components. This article gives an overview of the capabilities that DevExtreme provides for implementing and applying templates.

NOTE
For documentation on templates in DevExtreme ASP.NET MVC Controls, refer to Implementing Templates (for ASP.NET MVC 5) or Templates (for ASP.NET Core).

Default Templates

Default templates are based on data source fields. You can control appearance by adding or removing particular fields from data source objects. For example, the List UI component's default template for items contains the text, visible, and disabled fields, among others. If you assign the following array to the UI component's items or dataSource property, the first item will be disabled, the second hidden, both of them will have text, and the third item will render a custom markup:

JavaScript
function customMarkup() {
    var d = document.createElement("div");
    d.innerHTML = "<i>Oranges</i>";
    return d;
}
var fruits = [
    { text: "Apples", disabled: true },
    { text: "Lemons", visible: false },
    { template: customMarkup }
];

You can achieve the same in the markup using the dxItem component that supports default and custom templates. Do not set the UI component's dataSource property in this case.

jQuery
HTML
JavaScript
<div id="list">
    <div data-options="dxItem: { text: 'Apples', disabled: true }"></div>
    <div data-options="dxItem: { text: 'Lemons', visible: false }"></div>
    <div data-options="dxItem: { }">
        <i>Oranges</i>
    </div>
</div>
$(function() {
    $("#list").dxList({/* ... */});
});
Angular
app.component.html
app.module.ts
<dx-list>
    <dxi-item text="Apples" [disabled]="true"></dxi-item>
    <dxi-item text="Lemons" [visible]="false"></dxi-item>
    <dxi-item>
        <i>Oranges</i>
    </dxi-item>
</dx-list>
import { DxListModule } from "devextreme-angular";
// ...
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
export class AppModule { }
AngularJS
HTML
JavaScript
<div dx-list="{ }">
    <div data-options="dxItem: { text: 'Apples', disabled: true }"></div>
    <div data-options="dxItem: { text: 'Lemons', visible: false }"></div>
    <div data-options="dxItem: { }">
        <i>Oranges</i>
    </div>
</div>
angular.module('DemoApp', ['dx'])
    .controller('DemoController', function ($scope) {
        // ...
    });
Knockout
HTML
JavaScript
<div data-bind="dxList: { ... }">
    <div data-options="dxItem: { text: 'Apples', disabled: true }"></div>
    <div data-options="dxItem: { text: 'Lemons', visible: false }"></div>
    <div data-options="dxItem: { }">
        <i>Oranges</i>
    </div>
</div>
var viewModel = {
    // ...
};

ko.applyBindings(viewModel);
Vue
App.vue
<template>
    <DxList>
        <DxItem text="Apples" :disabled="true" />
        <DxItem text="Lemons" :visible="false" />
        <DxItem>
            <template #default>
                <i>Oranges</i>
            </template>
        </DxItem>
    </DxList>
</template>

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

import DxList, {
    DxItem
} from 'devextreme-vue/list';

export default {
    components: {
        DxList,
        DxItem
    }
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import List, { Item } from 'devextreme-react/list';

class App extends React.Component {
    render() {
        return (
            <List>
                <Item text="Apples" disabled={true} />
                <Item text="Lemons" visible={false} />
                <Item>
                    <i>Oranges</i>
                </Item>
            </List>
        );
    }
}
export default App;

Default templates and the fields available in them depend on the UI component. Refer to the items property description of a particular UI component for a list of template fields.

Custom Templates

jQuery

Templates are passed as properties that end with ...Template. Each template has access to the following parameters:

Angular

Templates are passed as properties that end with ...Template. Each template has access to the following parameters:

Vue

Templates are passed as properties that end with ...Template. Each template has access to the following parameters:

React

Templates are passed as properties that end with ...Render or ...Component. Each template has access to the following parameters:

  • data
    A data source object or an object with fields specific to a particular template. For information on the contents of data, refer to the Template Data section of the template's API reference article.

  • index
    A zero-based index of the item in the collection. Available only in collection UI component templates.

  • element
    A jQuery element that represents the UI component element being customized. Available only if you use jQuery.

The following code shows how to declare a template and use these parameters. This code declares an itemTemplate for the List UI component:

jQuery
index.js
$(function() {
    $("#listContainer").dxList({
        items: [
            { itemProperty: "someValue" },
            // ...
        ],
        itemTemplate: function (data, index, element) {
            return index + " - " + data.itemProperty;

            // ===== or using the "element" parameter =====
            const $item = $("<div>").text(
                index + " - " + data.itemProperty
            );
            element.append($item);
        }
    });
});
Angular
app.component.html
app.component.ts
app.module.ts
<dx-list
    [items]="listData"
    itemTemplate="list-item">
    <div *dxTemplate="let data of 'list-item'; let index = index">
        {{index}} - {{data.itemProperty}}
    </div>
</dx-list>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    listData = [
        { itemProperty: "someValue" },
        // ...
    ]
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { DxListModule } from 'devextreme-angular';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        DxListModule
    ],
    providers: [ ],
    bootstrap: [AppComponent]
})
export class AppModule { }
Vue
App.vue
<template>
    <DxList
        :items="listData"
        item-template="list-item">
        <template #list-item="{ data, index }">
            {{ index }} - {{ data.itemProperty }}
        </template>
    </DxList>
</template>

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

import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    data() {
        return {
            listData: [
                { itemProperty: 'someValue' },
                // ...
            ]
        }
    }
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import List from 'devextreme-react/list';

const renderListItem = (data, index) => {
    return (
        <div>{index} - {data.itemProperty}</div>
    );
}

class App extends React.Component {
    listData = [
        { itemProperty: 'someValue' },
        // ...
    ];

    render() {
        return (
            <List
                items={this.listData}
                itemRender={renderListItem}
            />
        );
    }
}
export default App;

Collection UI components also support templates for individual items. Do not specify the UI component's dataSource property if you use individual templates.

jQuery
index.js
$(function() {
    $("#listContainer").dxList({
        items: [{
            template: function () {
                return $("<i>").text("Item 1")
            }
        }, {
            template: function () {
                return $("<b>").text("Item 2")
            }
        },{
            template: function () {
                return $("<div>").append(
                    $("<span>").text("Item with nested component"),
                    $("<div>").dxButton({
                        text: "Click me"
                    })
                )
            }
        }]
    });
});
Angular

Declare named templates within the component's markup but outside the templated element. Non-named templates should be declared inside the templated element.

app.component.html
app.module.ts
<dx-list>
    <dxi-item>
        <i>Item 1</i>
    </dxi-item>
    <dxi-item>
        <b>Item 2</b>
    </dxi-item>
    <dxi-item>
        <div *dxTemplate>
            Item with a nested component
            <dx-button text="Click me"></dx-button>
        </div>
    </dxi-item>
</dx-list>
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { DxListModule, DxButtonModule } from 'devextreme-angular';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        DxListModule,
        DxButtonModule
    ],
    providers: [ ],
    bootstrap: [AppComponent]
})
export class AppModule { }
Vue

Declare named templates within the component's markup but outside the templated element. Non-named templates should be declared inside the templated element.

App.vue
<template>
    <DxList>
        <DxItem>
            <template #default>
                <i>Item 1</i>
            </template>
        </DxItem>
        <DxItem>
            <template #default>
                <i>Item 2</i>
            </template>
        </DxItem>
        <DxItem>
            <template #default>               
                <div>
                    Item with a nested component
                    <DxButton text="Click me" />
                </div>
            </template>
        </DxItem>
    </DxList>
</template>

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

import DxList, {
    DxItem
} from 'devextreme-vue/list';
import DxButton from 'devextreme-vue/button';

export default {
    components: {
        DxList,
        DxItem,
        DxButton
    }
}
</script>
React
App.js
import React from 'react';
import 'devextreme/dist/css/dx.light.css';

import List, { Item } from 'devextreme-react/list';
import Button from 'devextreme-react/button';

class App extends React.Component {
    render() {
        return (
            <List>
                <Item>
                    <i>Item 1</i>
                </Item>
                <Item>
                    <i>Item 2</i>
                </Item>
                <Item>
                    Item with a nested component
                    <Button text="Click me" />
                </Item>
            </List>
        );
    }
}
export default App;

3rd-Party Template Engines

You can use a 3rd-party template engine, but only with jQuery. DevExtreme supports the following template engines out of the box:

To use one of them, pass its name to the DevExpress.setTemplateEngine(name) method:

JavaScript
HTML
DevExpress.setTemplateEngine("underscore");

$(function() {
    $("#list").dxList({
        // ...
        itemTemplate: $("#itemTemplate")
    });
})
<div id="list"></div>
<script type="text/html" id="itemTemplate">
    <!-- your Underscore template -->
</script>

View Demo

You can also use other template engines, but you need to implement functions that compile and render templates in this case. See DevExpress.setTemplateEngine(options) for details.