React List - In the Data Source

Items in the List are grouped if they are grouped in the data source. The List recognizes a group when it encounters an object with the key and items fields. The key is the group header, the items are items that fell into the group. For example, the fruitsVegetables array from the following code produces two groups with three items each. Note that the List needs to be informed that it deals with grouped data, therefore its grouped property is set to true.

jQuery
JavaScript
const fruitsVegetables = [{
    key: "Fruits",
    items: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    key: "Vegetables",
    items: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

$(function() {
    $("#listContainer").dxList({
        dataSource: fruitsVegetables,
        grouped: true,
        itemTemplate: function(data, _, element) {
            element.append(
                $("<p>").text(data.name + " | " + data.count).css("margin", 0)
            )
        }
    });
});
Angular
TypeScript
HTML
import { DxListModule } from "devextreme-angular";
// ...
export class AppComponent {
    fruitsVegetables = [{
        key: "Fruits",
        items: [
            { name: "Apples", count: 10 },
            { name: "Oranges", count: 12 },
            { name: "Lemons", count: 15 }
        ]
    }, {
        key: "Vegetables",
        items: [
            { name: "Potatoes", count: 5 },
            { name: "Tomatoes", count: 9 },
            { name: "Turnips", count: 8 }
        ]
    }];
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
<dx-list
    [dataSource]="fruitsVegetables"
    [grouped]="true">
    <div *dxTemplate="let data of 'item'">
        <p style="margin:0px">{{data.name}} | {{data.count}}</p>
    </div>
</dx-list>
Vue
App.vue
<template>
    <DxList
        :data-source="fruitsVegetables"
        :grouped="true"
        item-template="list-item">
        <template #list-item="{ data }">
            <p style="margin:0px">{{ data.name }} | {{ data.count }}</p>
        </template>
    </DxList>
</template>

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

import DxList from 'devextreme-vue/list';

const fruitsVegetables = [{
    key: "Fruits",
    items: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    key: "Vegetables",
    items: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

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

import List from 'devextreme-react/list';

const fruitsVegetables = [{
    key: "Fruits",
    items: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    key: "Vegetables",
    items: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

const ListItem = (data) => {
    return (
        <p style={{ margin: '0px' }}>{ data.name } | { data.count }</p>
    );
};

export default function App() {
    return (
        <List
            dataSource={fruitsVegetables}
            grouped={true}
            itemRender={ListItem}
        />
    );
}
NOTE
Only one-level grouping is supported.

View Demo

If objects in your data source miss the key and items fields, use the map function of the DevExtreme DataSource to bring these objects to the key + items structure. You can find more information on the map function in the Data Layer - Item Mapping topic.

jQuery
JavaScript
const fruitsVegetables = [{
    type: "Fruits",
    collection: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    type: "Vegetables",
    collection: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

$(function() {
    $("#listContainer").dxList({
        dataSource: new DevExpress.data.DataSource({
            store: fruitsVegetables,
            map: function(item) {
                return {
                    key: item.type,
                    items: item.collection
                }
            }
        }),
        grouped: true,
        itemTemplate: function(data, _, element) {
            element.append(
                $("<p>").text(data.name + " | " + data.count).css("margin", 0)
            )
        }
    });
});
Angular
TypeScript
HTML
import { DxListModule } from "devextreme-angular";
import DataSource from "devextreme/data/data_source";
// ...
export class AppComponent {
    fruitsVegetables = [{
        type: "Fruits",
        collection: [
            { name: "Apples", count: 10 },
            { name: "Oranges", count: 12 },
            { name: "Lemons", count: 15 }
        ]
    }, {
        type: "Vegetables",
        collection: [
            { name: "Potatoes", count: 5 },
            { name: "Tomatoes", count: 9 },
            { name: "Turnips", count: 8 }
        ]
    }];
    listDataSource = new DataSource({
        store: this.fruitsVegetables,
        map: function (item) {
            return {
                key: item.type,
                items: item.collection
            }  
        }
    });
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
<dx-list
    [dataSource]="listDataSource"
    [grouped]="true">
    <div *dxTemplate="let data of 'item'">
        <p style="margin:0px">{{data.name}} | {{data.count}}</p>
    </div>
</dx-list>
Vue
App.vue
<template>
    <DxList
        :data-source="listDataSource"
        :grouped="true"
        item-template="list-item">
        <template #list-item="{ data }">
            <p style="margin:0px">{{ data.name }} | {{ data.count }}</p>
        </template>
    </DxList>
</template>

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

import DxList from 'devextreme-vue/list';
import DataSource from 'devextreme/data/data_source';

const fruitsVegetables = [{
    type: "Fruits",
    collection: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    type: "Vegetables",
    collection: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

const listDataSource = new DataSource({
    store: fruitsVegetables,
    map: function (item) {
        return {
            key: item.type,
            items: item.collection
        }  
    }
});

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

import List from 'devextreme-react/list';
import DataSource from 'devextreme/data/data_source';

const fruitsVegetables = [{
    type: "Fruits",
    collection: [
        { name: "Apples", count: 10 },
        { name: "Oranges", count: 12 },
        { name: "Lemons", count: 15 }
    ]
}, {
    type: "Vegetables",
    collection: [
        { name: "Potatoes", count: 5 },
        { name: "Tomatoes", count: 9 },
        { name: "Turnips", count: 8 }
    ]
}];

const listDataSource = new DataSource({
    store: fruitsVegetables,
    map: function (item) {
        return {
            key: item.type,
            items: item.collection
        }  
    }
});

const ListItem = (data) => {
    return (
        <p style={{ margin: '0px' }}>{ data.name } | { data.count }</p>
    );
};

export default function App() {
    return (
        <List
            dataSource={listDataSource}
            grouped={true}
            itemRender={ListItem}
        />
    );
}

If your data is not grouped at all, you can group it using the group property of the DataSource. See the Data Layer - Grouping topic for details.

jQuery
JavaScript
const fruitsVegetables = [
    { type: "Fruits", name: "Apples", count: 10 },
    { type: "Fruits", name: "Oranges", count: 12 },
    { type: "Fruits", name: "Lemons", count: 15 },
    { type: "Vegetables", name: "Potatoes", count: 5 },
    { type: "Vegetables", name: "Tomatoes", count: 9 },
    { type: "Vegetables", name: "Turnips", count: 8 }
];

$(function() {
    $("#listContainer").dxList({
        dataSource: new DevExpress.data.DataSource({
            store: fruitsVegetables,
            group: "type"
        }),
        grouped: true,
        itemTemplate: function(data, _, element) {
            element.append(
                $("<p>").text(data.name + " | " + data.count).css("margin", 0)
            )
        }
    });
});
Angular
TypeScript
HTML
import { DxListModule } from "devextreme-angular";
import DataSource from "devextreme/data/data_source";
// ...
export class AppComponent {
    fruitsVegetables = [
        { type: "Fruits", name: "Apples", count: 10 },
        { type: "Fruits", name: "Oranges", count: 12 },
        { type: "Fruits", name: "Lemons", count: 15 },
        { type: "Vegetables", name: "Potatoes", count: 5 },
        { type: "Vegetables", name: "Tomatoes", count: 9 },
        { type: "Vegetables", name: "Turnips", count: 8 }
    ];
    listDataSource = new DataSource({
        store: this.fruitsVegetables,
        group: "type"
    });
}
@NgModule({
    imports: [
        // ...
        DxListModule
    ],
    // ...
})
<dx-list
    [dataSource]="listDataSource"
    [grouped]="true">
    <div *dxTemplate="let data of 'item'">
        <p style="margin:0px">{{data.name}} | {{data.count}}</p>
    </div>
</dx-list>
Vue
App.vue
<template>
    <DxList
        :data-source="listDataSource"
        :grouped="true"
        item-template="list-item">
        <template #list-item="{ data }">
            <p style="margin:0px">{{ data.name }} | {{ data.count }}</p>
        </template>
    </DxList>
</template>

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

import DxList from 'devextreme-vue/list';
import DataSource from 'devextreme/data/data_source';

const fruitsVegetables = [
    { type: "Fruits", name: "Apples", count: 10 },
    { type: "Fruits", name: "Oranges", count: 12 },
    { type: "Fruits", name: "Lemons", count: 15 },
    { type: "Vegetables", name: "Potatoes", count: 5 },
    { type: "Vegetables", name: "Tomatoes", count: 9 },
    { type: "Vegetables", name: "Turnips", count: 8 }
];

const listDataSource = new DataSource({
    store: fruitsVegetables,
    group: "type"
});

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

import List from 'devextreme-react/list';
import DataSource from 'devextreme/data/data_source';

const fruitsVegetables = [
    { type: "Fruits", name: "Apples", count: 10 },
    { type: "Fruits", name: "Oranges", count: 12 },
    { type: "Fruits", name: "Lemons", count: 15 },
    { type: "Vegetables", name: "Potatoes", count: 5 },
    { type: "Vegetables", name: "Tomatoes", count: 9 },
    { type: "Vegetables", name: "Turnips", count: 8 }
];

const listDataSource = new DataSource({
    store: fruitsVegetables,
    group: "type"
});

const ListItem = (data) => {
    return (
        <p style={{ margin: '0px' }}>{ data.name } | { data.count }</p>
    );
};

export default function App() {
    return (
        <List
            dataSource={listDataSource}
            grouped={true}
            itemRender={ListItem}
        />
    );
}
See Also