DevExtreme v23.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Master-Detail View

The Master-Detail View allows users to expand a row ('master') and display the related content ('details') in the expanded section. To configure this feature, set the the masterDetail object's enabled property to true and use a template to specify detail section content. In this demo, the detail section displays another DataGrid.

Backend API
<template> <DxDataGrid id="grid-container" :show-borders="true" :data-source="employees" key-expr="ID" > <DxColumn :width="70" data-field="Prefix" caption="Title" /> <DxColumn data-field="FirstName"/> <DxColumn data-field="LastName"/> <DxColumn :width="170" data-field="Position" /> <DxColumn :width="125" data-field="State" /> <DxColumn data-field="BirthDate" data-type="date" /> <DxMasterDetail :enabled="true" template="masterDetailTemplate" /> <template #masterDetailTemplate="{ data: employee }"> <DetailTemplate :template-data="employee" /> </template> </DxDataGrid> </template> <script setup lang="ts"> import { DxDataGrid, DxColumn, DxMasterDetail, } from 'devextreme-vue/data-grid'; import DetailTemplate from './DetailTemplate.vue'; import { employees } from './data.ts'; </script> <style> #grid-container { height: 440px; } </style>
<template> <div> <div class="master-detail-caption">{{ detailInfo }}</div> <DxDataGrid :data-source="dataSource" :show-borders="true" :column-auto-width="true" > <DxColumn data-field="Subject"/> <DxColumn data-field="StartDate" data-type="date" /> <DxColumn data-field="DueDate" data-type="date" /> <DxColumn data-field="Priority"/> <DxColumn :calculate-cell-value="completedValue" data-type="boolean" caption="Completed" /> </DxDataGrid> </div> </template> <script setup lang="ts"> import { reactive } from 'vue'; import { DxDataGrid, DxColumn, DxDataGridTypes } from 'devextreme-vue/data-grid'; import ArrayStore from 'devextreme/data/array_store'; import DataSource from 'devextreme/data/data_source'; import { tasks, Task } from './data.ts'; const props = defineProps<{ templateData: DxDataGridTypes.MasterDetailTemplateData }>(); const dataSource = getTasks(props.templateData.key); const itemData = reactive(props.templateData.data); const detailInfo = `${itemData.FirstName} ${itemData.LastName}'s Tasks:`; const completedValue = (rowData: Task) => rowData.Status === 'Completed'; function getTasks(key: number) { return new DataSource({ store: new ArrayStore({ data: tasks, key: 'ID', }), filter: ['EmployeeID', '=', key], }); } </script> <style> .master-detail-caption { padding: 0 0 5px 10px; font-size: 14px; font-weight: bold; } </style>
window.exports = window.exports || {}; window.config = { transpiler: 'plugin-babel', meta: { '*.vue': { loader: 'vue-loader', }, '*.ts': { loader: 'demo-ts-loader', }, '*.svg': { loader: 'svg-loader', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'root:': '../../../../../', 'npm:': 'https://unpkg.com/', }, map: { 'vue': 'npm:vue@3.3.4/dist/vue.esm-browser.js', 'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js', 'demo-ts-loader': 'root:utils/demo-ts-loader.js', 'svg-loader': 'root:utils/svg-loader.js', 'mitt': 'npm:mitt/dist/mitt.umd.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@23.2.5/cjs', 'devextreme-vue': 'npm:devextreme-vue@23.2.5/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.6.4/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.51/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.4/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js', }, packages: { 'devextreme-vue': { main: 'index.js', }, 'devextreme': { defaultExtension: 'js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.12/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, }, }; System.config(window.config);
export type Task = { ID: number; Subject: string; StartDate: string; DueDate: string; Status: string; Priority: string; Completion: number; EmployeeID: number; }; export type Employee = { ID: number; FirstName: string; LastName: string; Prefix: string; Position: string; BirthDate: string; State: string; }; export const employees: Employee[] = [{ ID: 1, Prefix: 'Mr.', FirstName: 'John', LastName: 'Heart', Position: 'CEO', State: 'California', BirthDate: '1964/03/16', }, { ID: 2, Prefix: 'Mrs.', FirstName: 'Olivia', LastName: 'Peyton', Position: 'Sales Assistant', State: 'California', BirthDate: '1981/06/03', }, { ID: 3, Prefix: 'Mr.', FirstName: 'Robert', LastName: 'Reagan', Position: 'CMO', State: 'Arkansas', BirthDate: '1974/09/07', }, { ID: 4, Prefix: 'Ms.', FirstName: 'Greta', LastName: 'Sims', Position: 'HR Manager', State: 'Georgia', BirthDate: '1977/11/22', }, { ID: 5, Prefix: 'Mr.', FirstName: 'Brett', LastName: 'Wade', Position: 'IT Manager', State: 'Idaho', BirthDate: '1968/12/01', }, { ID: 6, Prefix: 'Mrs.', FirstName: 'Sandra', LastName: 'Johnson', Position: 'Controller', State: 'Utah', BirthDate: '1974/11/15', }, { ID: 7, Prefix: 'Mr.', FirstName: 'Kevin', LastName: 'Carter', Position: 'Shipping Manager', State: 'California', BirthDate: '1978/01/09', }, { ID: 8, Prefix: 'Ms.', FirstName: 'Cynthia', LastName: 'Stanwick', Position: 'HR Assistant', State: 'Arkansas', BirthDate: '1985/06/05', }, { ID: 9, Prefix: 'Dr.', FirstName: 'Kent', LastName: 'Samuelson', Position: 'Ombudsman', State: 'Missouri', BirthDate: '1972/09/11', }]; export const tasks: Task[] = [{ ID: 1, Subject: 'Prepare 2013 Financial', StartDate: '2013/01/15', DueDate: '2013/01/31', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 8, }, { ID: 2, Subject: 'Prepare 3013 Marketing Plan', StartDate: '2013/01/01', DueDate: '2013/01/31', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 5, }, { ID: 3, Subject: 'Update Personnel Files', StartDate: '2013/02/03', DueDate: '2013/02/28', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 2, }, { ID: 4, Subject: 'Review Health Insurance Options Under the Affordable Care Act', StartDate: '2013/02/12', DueDate: '2013/04/25', Status: 'In Progress', Priority: 'High', Completion: 50, EmployeeID: 2, }, { ID: 5, Subject: 'Choose between PPO and HMO Health Plan', StartDate: '2013/02/15', DueDate: '2013/04/15', Status: 'In Progress', Priority: 'High', Completion: 75, EmployeeID: 1, }, { ID: 6, Subject: 'Google AdWords Strategy', StartDate: '2013/02/16', DueDate: '2013/02/28', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 1, }, { ID: 7, Subject: 'New Brochures', StartDate: '2013/02/17', DueDate: '2013/02/24', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 1, }, { ID: 11, Subject: 'Rollout of New Website and Marketing Brochures', StartDate: '2013/02/20', DueDate: '2013/02/28', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 5, }, { ID: 12, Subject: 'Update Sales Strategy Documents', StartDate: '2013/02/20', DueDate: '2013/02/22', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 9, }, { ID: 15, Subject: 'Review 2012 Sales Report and Approve 2013 Plans', StartDate: '2013/02/23', DueDate: '2013/02/28', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 5, }, { ID: 16, Subject: 'Deliver R&D Plans for 2013', StartDate: '2013/03/01', DueDate: '2013/03/10', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 3, }, { ID: 20, Subject: 'Approve Hiring of John Jeffers', StartDate: '2013/03/02', DueDate: '2013/03/12', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 4, }, { ID: 20, Subject: 'Approve Hiring of John Jeffers', StartDate: '2013/03/02', DueDate: '2013/03/12', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 6, }, { ID: 21, Subject: 'Non-Compete Agreements', StartDate: '2013/03/12', DueDate: '2013/03/14', Status: 'Completed', Priority: 'Low', Completion: 100, EmployeeID: 2, }, { ID: 22, Subject: 'Update NDA Agreement', StartDate: '2013/03/14', DueDate: '2013/03/16', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 1, }, { ID: 23, Subject: 'Update Employee Files with New NDA', StartDate: '2013/03/16', DueDate: '2013/03/26', Status: 'Need Assistance', Priority: 'Normal', Completion: 90, EmployeeID: 4, }, { ID: 24, Subject: 'Update Employee Files with New NDA', StartDate: '2013/03/16', DueDate: '2013/03/26', Status: 'Need Assistance', Priority: 'Normal', Completion: 90, EmployeeID: 6, }, { ID: 25, Subject: 'Sign Updated NDA', StartDate: '2013/03/20', DueDate: '2013/03/25', Status: 'Completed', Priority: 'Urgent', Completion: 100, EmployeeID: 7, }, { ID: 26, Subject: 'Sign Updated NDA', StartDate: '2013/03/20', DueDate: '2013/03/25', Status: 'Completed', Priority: 'Urgent', Completion: 100, EmployeeID: 8, }, { ID: 27, Subject: 'Sign Updated NDA', StartDate: '2013/03/20', DueDate: '2013/03/25', Status: 'Need Assistance', Priority: 'Urgent', Completion: 25, EmployeeID: 9, }, { ID: 35, Subject: 'Update Revenue Projections', StartDate: '2013/03/24', DueDate: '2013/04/07', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 8, }, { ID: 36, Subject: 'Review Revenue Projections', StartDate: '2013/03/25', DueDate: '2013/04/06', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 9, }, { ID: 40, Subject: 'Provide New Health Insurance Docs', StartDate: '2013/03/28', DueDate: '2013/04/07', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 4, }, { ID: 41, Subject: 'Provide New Health Insurance Docs', StartDate: '2013/03/28', DueDate: '2013/04/07', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 6, }, { ID: 50, Subject: 'Give Final Approval for Refunds', StartDate: '2013/05/05', DueDate: '2013/05/15', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 2, }, { ID: 52, Subject: 'Review Product Recall Report by Engineering Team', StartDate: '2013/05/17', DueDate: '2013/05/20', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 1, }, { ID: 55, Subject: 'Review Overtime Report', StartDate: '2013/06/10', DueDate: '2013/06/14', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 7, }, { ID: 60, Subject: 'Refund Request Template', StartDate: '2013/06/17', DueDate: '2014/04/01', Status: 'Deferred', Priority: 'Normal', Completion: 0, EmployeeID: 9, }, { ID: 71, Subject: 'Upgrade Server Hardware', StartDate: '2013/07/22', DueDate: '2013/07/31', Status: 'Completed', Priority: 'Urgent', Completion: 100, EmployeeID: 7, }, { ID: 72, Subject: 'Upgrade Personal Computers', StartDate: '2013/07/24', DueDate: '2014/04/30', Status: 'In Progress', Priority: 'Normal', Completion: 85, EmployeeID: 7, }, { ID: 74, Subject: 'Decide on Mobile Devices to Use in the Field', StartDate: '2013/07/30', DueDate: '2013/08/02', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 3, }, { ID: 78, Subject: 'Try New Touch-Enabled WinForms Apps', StartDate: '2013/08/11', DueDate: '2013/08/15', Status: 'Completed', Priority: 'Normal', Completion: 100, EmployeeID: 3, }, { ID: 81, Subject: 'Review Site Up-Time Report', StartDate: '2013/08/24', DueDate: '2013/08/30', Status: 'Completed', Priority: 'Urgent', Completion: 100, EmployeeID: 5, }, { ID: 99, Subject: 'Submit D&B Number to ISP for Credit Approval', StartDate: '2013/11/04', DueDate: '2013/11/07', Status: 'Completed', Priority: 'High', Completion: 100, EmployeeID: 8, }, { ID: 117, Subject: 'Approval on Converting to New HDMI Specification', StartDate: '2014/01/11', DueDate: '2014/01/31', Status: 'Deferred', Priority: 'Normal', Completion: 75, EmployeeID: 3, }, { ID: 138, Subject: 'Review HR Budget Company Wide', StartDate: '2014/03/20', DueDate: '2014/03/25', Status: 'In Progress', Priority: 'Normal', Completion: 40, EmployeeID: 6, }, { ID: 145, Subject: 'Final Budget Review', StartDate: '2014/03/26', DueDate: '2014/03/27', Status: 'In Progress', Priority: 'High', Completion: 25, EmployeeID: 6, }];
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!DOCTYPE html> <html> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx.light.css" /> <script type="module"> import * as vueCompilerSFC from "https://unpkg.com/@vue/compiler-sfc@3.3.4/dist/compiler-sfc.esm-browser.js"; window.vueCompilerSFC = vueCompilerSFC; </script> <script src="https://unpkg.com/typescript@4.2.4/lib/typescript.js"></script> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.ts"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"> </div> </div> </body> </html>