Angular DataGrid - masterDetail

Allows you to build a master-detail interface in the grid.

Selector: dxo-master-detail
Type:

MasterDetail

In DataGrid, a master-detail interface supplies a usual data row with an expandable section that contains the details on this data row. In that case, the data row is called "master row", while the section is called "detail section".

To enable the master-detail interface, assign true to the masterDetail.enabled property. After that, specify the template for detail sections using the masterDetail.template property. Templates allow you to place virtually anything into the detail sections. For example, you can display another DataGrid or any other UI component there. For more information on specifying the template for the detail sections, see the template property description.

Master-Detail View Demo Advanced Master-Detail View Demo

See Also

autoExpandAll

Specifies whether detail sections appear expanded or collapsed.

Type:

Boolean

Default Value: false

NOTE
This feature is available only when all data is located locally.

enabled

Enables an end user to expand/collapse detail sections.

Type:

Boolean

Default Value: false

If you set this property to true, each grid row will be supplied with an arrow that allows an end user to expand/collapse the detail section of this row.

If the masterDetail.enabled property is false, the expanding arrows are missing. It makes detail sections unreachable for an end user.

Setting this property to false is recommended if you need a custom logic of expanding/collapsing the detail sections. When implementing this logic, you can use specific API methods. To check whether the detail section is expanded or collapsed, use the isRowExpanded(key) method. To expand or collapse a specific detail section, call the expandRow(key) or collapseRow(key) method respectively.

Master-Detail View Demo Advanced Master-Detail View Demo

See Also

template

Specifies a custom template for detail sections.

Type:

template

Template Data:
Name Type Description
watch

Function

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.

key any

The master row's key.

data

Object

The master row's data object.

Master-Detail View Demo Advanced Master-Detail View Demo

You should call the updateDimensions() method each time the size of the detail section's content changes to make the table layout automatically adapt its size. In the following code, the TabPanel in the detail section contains views that can have different heights. The updateDimensions method is called in the onSelectionChanged handler to update the table layout when another view is selected.

jQuery
JavaScript
$("#dataGridContainer").dxDataGrid({
    // ...
    masterDetail: {
        enabled: true,
        template: function (container, info) {
            $("<div>").dxTabPanel({ 
                // ...
                onSelectionChanged: function () {
                    // ...
                    $("#dataGridContainer").dxDataGrid("instance").updateDimensions();
                }
            }).appendTo(container); 
        }
    }
});
Angular
HTML
TypeScript
<dx-data-grid ... >
    <dxo-master-detail
        [enabled]="true"
        [template]="'detail'">
    </dxo-master-detail>
    <div *dxTemplate="let info of 'detail'">
        <dx-tab-panel ... 
            (onSelectionChanged)="onSelectionChanged()">
        </dx-tab-panel>
    </div>
</dx-data-grid>
import { DxDataGridModule, DxDataGridComponent, DxTabPanelModule } from "devextreme-angular";
// ...
export class AppComponent {
    @ViewChild(DxDataGridComponent, { static: false }) dataGrid: DxDataGridComponent
    // Prior to Angular 8
    // @ViewChild(DxDataGridComponent) dataGrid: DxDataGridComponent
    onSelectionChanged () {
        // ...
        this.dataGrid.instance.updateDimensions();
    }
}
@NgModule({
    imports: [
        // ...
        DxDataGridModule,
        DxTabPanelModule
    ],
    // ...
})
Vue
App.vue
<template>
    <DxDataGrid ...
        :ref="dataGridRefKey">
        <DxMasterDetail
            :enabled="true"
            template="detail"
        />
        <template #detail="{ data }">
            <DxTabPanel ... 
                @selection-changed="onSelectionChanged">
            </DxTabPanel>
        </template>
    </DxDataGrid>
</template>

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

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

const dataGridRefKey = "my-data-grid";

export default {
    components: {
        DxDataGrid,
        DxMasterDetail
    },
    data: function() {
        return {
            dataGridRefKey
        };
    },
    methods: {
        onSelectionChanged() {
            // ...
            this.dataGrid.updateDimensions();
        }
    },
    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, {
    MasterDetail
} from 'devextreme-react/data-grid';
import TabPanel from 'devextreme-react/tab-panel';

const DetailSection = (data, updateGridDimensions) => {
    const onSelectionChanged = useCallback(() => {
        // ...
        updateGridDimensions();
    }, []);

    return (
        <TabPanel ... 
            onSelectionChanged>
        </TabPanel>
    );
};

export default function App() {
    const dataGrid = useRef(null);

    const updateGridDimensions = () => {
        dataGrid.current.instance().updateDimensions();
    };

    const renderDetailSection = useCallback(({ data }) => {
        return DetailSection(data, updateGridDimensions);
    }, []);

    return (
        <DataGrid ...
            ref={dataGrid}>
            <MasterDetail
                enabled={true}
                render={renderDetailSection}
            />
        </DataGrid>
    );
}
jQuery

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

index.js
$("#dataGridContainer").dxDataGrid({
    // ...
    masterDetail: {
        enabled: true,
        template: function (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.Amount);
        }
    }
});

View on GitHub

See Also