All docs
V21.1
21.2
21.1
20.2
20.1
19.2
The page you are viewing does not exist in version 19.2. This link will take you to the root page.
19.1
The page you are viewing does not exist in version 19.1. This link will take you to the root page.
18.2
The page you are viewing does not exist in version 18.2. This link will take you to the root page.
18.1
The page you are viewing does not exist in version 18.1. This link will take you to the root page.
17.2
The page you are viewing does not exist in version 17.2. This link will take you to the root page.

Master-Detail Interface

Watch Video

NOTE
You must specify the DataGrid's keyExpr or the Store's key property to ensure that the master-detail interface works properly.
See Also

User Interaction

The master-detail interface supplies a standard data row with an expandable section that contains detail data. In master-detail terms, the data row is called "master row" and the expandable section - "detail section".

DevExtreme HTML5/JavaScript DataGrid UI component Master Detail Interface

The master-detail interface becomes available after you specify the detail sections' contents using the masterDetail.template property. You can expand and collapse detail sections programmatically or enable a user to do it by setting the masterDetail.enabled property to true. Set the masterDetail.autoExpandAll property to true to expand these sections by default.

jQuery
JavaScript
$(function() {
    $("#dataGridContainer").dxDataGrid({
        // ...
        masterDetail: {
            enabled: true,
            autoExpandAll: true,
            template: function (container, info) {
                сonst currentEmployeeData = info.data;
                container.append(
                    $('<div class="employeeInfo">
                        <img class="employeePhoto" src="' + currentEmployeeData.Picture + '" />
                        <p class="employeeNotes">' + currentEmployeeData.Notes + '</p>
                    </div>')
                );
            } 
        }
    });
});
Angular
HTML
TypeScript
<dx-data-grid ... >
    <dxo-master-detail
        [enabled]="true"
        [autoExpandAll]="true"
        [template]="'detail'">
    </dxo-master-detail>
    <div *dxTemplate="let employee of 'detail'">
        <div class="employeeInfo">
            <img class="employeePhoto" [src]="employee.data.Picture" />
            <p class="employeeNotes">{{employee.data.Notes}}</p>
        </div>
    </div>
</dx-data-grid>
import { DxDataGridModule } from "devextreme-angular";
// ...
export class AppComponent {
    // ...
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxDataGrid ... >
        <DxMasterDetail
            :enabled="true"
            :auto-expand-all="true"
            template="detail"
        />
        <template #detail="{ data }">
            <div class="employeeInfo">
                <img class="employeePhoto" :src="data.Picture" />
                <p class="employeeNotes">{{ data.Notes }}</p>
            </div>
        </template>
    </DxDataGrid>
</template>

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

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

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

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

const DetailSection = ({ data }) => {
    return (
        <div class="employeeInfo">
            <img class="employeePhoto" src={data.Picture} />
            <p class="employeeNotes">{data.Notes}</p>
        </div>
    );
};

export default function App() {
    return (
        <DataGrid ... >
            <MasterDetail
                enabled={true}
                autoExpandAll={true}
                render={DetailSection}
            />
        </DataGrid>
    );
}

Once loaded, a detail section's content remains cached until a user switches to another page in the DataGrid or reloads the web page.

View Demo

API

Pass -1 to the expandAll(groupIndex) or collapseAll(groupIndex) method to expand or collapse all master rows at once.

jQuery
JavaScript
const dataGrid = $("#dataGridContainer").dxDataGrid("instance");
dataGrid.expandAll(-1);
dataGrid.collapseAll(-1);
Angular
TypeScript
import { ..., ViewChild } from "@angular/core";
import { DxDataGridModule, DxDataGridComponent } from "devextreme-angular";
// ...
export class AppComponent {
    @ViewChild(DxDataGridComponent, { static: false }) dataGrid: DxDataGridComponent;
    // Prior to Angular 8
    // @ViewChild(DxDataGridComponent) dataGrid: DxDataGridComponent;
    expandAllMasterRows () {
        this.dataGrid.instance.expandAll(-1);
    }
    collapseAllMasterRows () {
        this.dataGrid.instance.collapseAll(-1);
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxDataGrid ...
        :ref="dataGridRefKey">
        <!-- ... -->
    </DxDataGrid>
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxDataGrid, { ... } from 'devextreme-vue/data-grid';

const dataGridRefKey = "my-data-grid";

export default {
    components: {
        DxDataGrid,
        // ...
    },
    data: function() {
        return {
            dataGridRefKey
        };
    },
    methods: {
        expandAllMasterRows() {
            this.dataGrid.expandAll(-1);
        },
        collapseAllMasterRows() {
            this.dataGrid.collapseAll(-1);
        }
    },
    computed: {
        dataGrid: function() {
            return this.$refs[dataGridRefKey].instance;
        }
    }
}
</script>
React
App.js
import React, { useRef, useCallback } from 'react';
import 'devextreme/dist/css/dx.light.css';

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

export default function App() {
    const dataGrid = useRef(null);
    const expandAllMasterRows = useCallback(() => {
        dataGrid.current.instance.expandAll(-1);
    }, []);
    const collapseAllMasterRows = useCallback(() => {
        dataGrid.current.instance.collapseAll(-1);
    }, []);

    return (
        <DataGrid ...
            ref={dataGrid}>
            {/* ... */}
        </DataGrid>
    );
}

The expandRow(key) and collapseRow(key) methods expand and collapse an individual master row. You can check a row's current state by calling the isRowExpanded(key) method.

jQuery
JavaScript
function toggleMasterRow (rowKey) {
    const dataGrid = $("#dataGridContainer").dxDataGrid("instance");
    if (dataGrid.isRowExpanded(rowKey)) {
        dataGrid.collapseRow(rowKey);
    } else {
        dataGrid.expandRow(rowKey);
    }
}
Angular
TypeScript
import { ..., ViewChild } from "@angular/core";
import { DxDataGridModule, DxDataGridComponent } from "devextreme-angular";
// ...
export class AppComponent {
    @ViewChild(DxDataGridComponent, { static: false }) dataGrid: DxDataGridComponent;
    // Prior to Angular 8
    // @ViewChild(DxDataGridComponent) dataGrid: DxDataGridComponent;
    toggleMasterRow (rowKey) {
        if (this.dataGrid.instance.isRowExpanded(rowKey)) {
            this.dataGrid.instance.collapseRow(rowKey);
        } else {
            this.dataGrid.instance.expandRow(rowKey);
        }
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxDataGrid ...
        :ref="dataGridRefKey">
        <!-- ... -->
    </DxDataGrid>
</template>

<script>
import 'devextreme/dist/css/dx.light.css';
import DxDataGrid, { ... } from 'devextreme-vue/data-grid';

const dataGridRefKey = "my-data-grid";

export default {
    components: {
        DxDataGrid,
        // ...
    },
    data: function() {
        return {
            dataGridRefKey
        };
    },
    methods: {
        toggleMasterRow(rowKey) {
            if (this.dataGrid.isRowExpanded(rowKey)) {
                this.dataGrid.collapseRow(rowKey);
            } else {
                this.dataGrid.expandRow(rowKey);
            }
        }
    },
    computed: {
        dataGrid: function() {
            return this.$refs[dataGridRefKey].instance;
        }
    }
}
</script>
React
App.js
import React, { useRef, useCallback } from 'react';
import 'devextreme/dist/css/dx.light.css';

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

export default function App() {
    const dataGrid = useRef(null);
    const toggleMasterRow = useCallback((rowKey) => {
        if (dataGrid.current.instance.isRowExpanded(rowKey)) {
            dataGrid.current.instance.collapseRow(rowKey);
        } else {
            dataGrid.current.instance.expandRow(rowKey);
        }
    }, []);

    return (
        <DataGrid ...
            ref={dataGrid}>
            {/* ... */}
        </DataGrid>
    );
}

View Demo

Events

Events raised for a master row when a user expands or collapses it are identical to the events raised for expanding or collapsing a group. See this topic for details.