Your search did not match any results.
Data Grid

Advanced Master-Detail View

This demo illustrates an advanced master-detail view in the DataGrid component. Master rows represent suppliers. Detail sections contain TabPanel components with two tabs: Orders and Address. In the Orders tab, you can choose a supplier's product from the SelectBox, and the DataGrid under it will show orders placed on this product. The Address tab displays the supplier's address.

Backend API
Copy to CodePen
Apply
Reset
const url = 'https://js.devexpress.com/Demos/Mvc/api/DataGridAdvancedMasterDetailView'; $(() => { $('#gridContainer').dxDataGrid({ showBorders: true, dataSource: DevExpress.data.AspNet.createStore({ key: 'SupplierID', loadUrl: `${url}/GetSuppliers`, }), paging: { pageSize: 15, }, remoteOperations: true, columns: [ 'ContactName', 'ContactTitle', 'CompanyName', 'City', 'Country', ], masterDetail: { enabled: true, template: masterDetailTemplate, }, }); }); function masterDetailTemplate(_, masterDetailOptions) { return $('<div>').dxTabPanel({ items: [{ title: 'Orders', template: createOrdersTabTemplate(masterDetailOptions.data), }, { title: 'Address', template: createAddressTabTemplate(masterDetailOptions.data), }], }); } function createOrdersTabTemplate(masterDetailData) { return function () { let orderHistoryDataGrid; function onProductChanged(productID) { orderHistoryDataGrid.option('dataSource', createOrderHistoryStore(productID)); } function onDataGridInitialized(e) { orderHistoryDataGrid = e.component; } return $('<div>').addClass('form-container').dxForm({ labelLocation: 'top', items: [{ label: { text: 'Product' }, template: createProductSelectBoxTemplate(masterDetailData, onProductChanged), }, { label: { text: 'Order History' }, template: createOrderHistoryTemplate(onDataGridInitialized), }], }); }; } function createProductSelectBoxTemplate(masterDetailData, onProductChanged) { return function () { return $('<div>').dxSelectBox({ dataSource: DevExpress.data.AspNet.createStore({ key: 'ProductID', loadParams: { SupplierID: masterDetailData.SupplierID }, loadUrl: `${url}/GetProductsBySupplier`, }), valueExpr: 'ProductID', displayExpr: 'ProductName', deferRendering: false, onContentReady(e) { const firstItem = e.component.option('items[0]'); if (firstItem) { e.component.option('value', firstItem.ProductID); } }, onValueChanged(e) { onProductChanged(e.value); }, }); }; } function createOrderHistoryTemplate(onDataGridInitialized) { return function () { return $('<div>').dxDataGrid({ onInitialized: onDataGridInitialized, paging: { pageSize: 5, }, showBorders: true, columns: [ 'OrderID', { dataField: 'OrderDate', dataType: 'date', }, 'ShipCountry', 'ShipCity', { dataField: 'UnitPrice', format: 'currency', }, 'Quantity', { dataField: 'Discount', format: 'percent', }, ], summary: { totalItems: [{ column: 'UnitPrice', summaryType: 'sum', valueFormat: { format: 'currency', precision: 2, }, }, { column: 'Quantity', summaryType: 'count', }], }, }); }; } function createAddressTabTemplate(data) { return function () { return $('<div>').addClass('address-form form-container').dxForm({ formData: data, colCount: 2, customizeItem(item) { item.template = formItemTemplate; }, items: ['Address', 'City', 'Region', 'PostalCode', 'Country', 'Phone'], }); }; } function formItemTemplate(item) { return $('<span>').text(item.editorOptions.value); } function createOrderHistoryStore(productID) { return DevExpress.data.AspNet.createStore({ key: 'OrderID', loadParams: { ProductID: productID }, loadUrl: `${url}/GetOrdersByProduct`, }); }
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <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" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/22.2.6/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://cdn3.devexpress.com/jslib/22.2.6/js/dx.all.js"></script> <script src="https://unpkg.com/devextreme-aspnet-data@2.9.0/js/dx.aspnet.data.js"></script> <script src="index.js"></script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="gridContainer"></div> </div> </body> </html>
#gridContainer { height: 620px; } .dx-datagrid-rowsview .dx-master-detail-row:not(.dx-datagrid-edit-form) > .dx-datagrid-group-space, .dx-datagrid-rowsview .dx-master-detail-row:not(.dx-datagrid-edit-form) .dx-master-detail-cell { background-color: transparent; } .form-container { padding: 20px; } .address-form label { font-weight: bold; }