Your search did not match any results.
Data Grid

Advanced Master-Detail View

This demo illustrates an advanced master-detail view in the DataGrid widget. Master rows represent suppliers. Detail sections contain TabPanel widgets 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.

Copy to CodeSandBox
Apply
Reset
import React from 'react'; import { Form, Item } from 'devextreme-react/form'; const items = ['Address', 'City', 'Region', 'PostalCode', 'Country', 'Phone']; class AddressTab extends React.Component { render() { return ( <Form formData={this.props.data} colCount={2} className={'address-form form-container'} > { items.map((item, index) => <Item dataField={item} key={index} render={this.renderFormItem} /> ) } </Form> ); } renderFormItem(item) { return <span>{item.editorOptions.value}</span>; } } export default AddressTab;
import React from 'react'; import { Column, DataGrid, MasterDetail, Paging } from 'devextreme-react/data-grid'; import { createStore } from 'devextreme-aspnet-data-nojquery'; import MasterDetailView from './MasterDetailView.js'; const url = 'https://js.devexpress.com/Demos/Mvc/api/DataGridAdvancedMasterDetailView'; const suppliersData = createStore({ key: 'SupplierID', loadUrl: `${url}/GetSuppliers` }); class App extends React.Component { render() { return ( <DataGrid dataSource={suppliersData} remoteOperations={true} showBorders={true} id={'gridContainer'} > <MasterDetail enabled={true} component={MasterDetailView} /> <Paging pageSize={15} /> <Column dataField={'ContactName'} /> <Column dataField={'ContactTitle'} /> <Column dataField={'CompanyName'} /> <Column dataField={'City'} /> <Column dataField={'Country'} /> </DataGrid> ); } } export default App;
import React from 'react'; import { TabPanel, Item } from 'devextreme-react/tab-panel'; import AddressTab from './AddressTab.js'; import OrdersTab from './OrdersTab.js'; class MasterDetailView extends React.Component { constructor(props) { super(props); this.renderOrdersTab = this.renderOrdersTab.bind(this); this.renderAddressTab = this.renderAddressTab.bind(this); } render() { return ( <TabPanel> <Item title={'Orders'} render={this.renderOrdersTab} /> <Item title={'Address'} render={this.renderAddressTab} /> </TabPanel> ); } renderOrdersTab() { return <OrdersTab supplierId={this.props.data.key} />; } renderAddressTab() { return <AddressTab data={this.props.data.data} />; } } export default MasterDetailView;
import React from 'react'; import { Column, DataGrid, Paging, Summary, TotalItem, ValueFormat } from 'devextreme-react/data-grid'; import { createStore } from 'devextreme-aspnet-data-nojquery'; const url = 'https://js.devexpress.com/Demos/Mvc/api/DataGridAdvancedMasterDetailView'; class OrderHistory extends React.Component { constructor(props) { super(props); this.state = { orderHistoryStore: null }; } render() { return ( <DataGrid dataSource={this.state.orderHistoryStore} showBorders={true} > <Paging pageSize={5} /> <Column dataField={'OrderID'} /> <Column dataField={'OrderDate'} dataType={'date'} /> <Column dataField={'ShipCountry'} /> <Column dataField={'ShipCity'} /> <Column dataField={'UnitPrice'} format={'currency'} /> <Column dataField={'Quantity'} /> <Column dataField={'Discount'} format={'percent'} /> <Summary> <TotalItem column={'UnitPrice'} summaryType={'sum'}> <ValueFormat format={'currency'} precision={2} /> </TotalItem> <TotalItem column={'Quantity'} summaryType={'count'} /> </Summary> </DataGrid> ); } componentDidUpdate(prevProps) { const { productId } = this.props; if(prevProps.productId !== productId) { this.setState({ orderHistoryStore: createStore({ key: 'OrderID', loadParams: { ProductID: productId }, loadUrl: `${url}/GetOrdersByProduct` }) }); } } } export default OrderHistory;
import React from 'react'; import { Form, Item, Label } from 'devextreme-react/form'; import ProductSelectBox from './ProductSelectBox.js'; import OrderHistory from './OrderHistory.js'; class OrdersTab extends React.Component { constructor(props) { super(props); this.state = { chosenProductId: null }; this.productChanged = this.productChanged.bind(this); this.renderSelectBox = this.renderSelectBox.bind(this); this.renderOrderHistory = this.renderOrderHistory.bind(this); } render() { return ( <Form labelLocation={'top'} className={'form-container'} > <Item render={this.renderSelectBox}> <Label text={'Product'} /> </Item> <Item render={this.renderOrderHistory}> <Label text={'Order History'} /> </Item> </Form> ); } renderSelectBox() { return <ProductSelectBox supplierId={this.props.supplierId} productId={this.state.chosenProductId} onProductChanged={this.productChanged} />; } renderOrderHistory() { return <OrderHistory productId={this.state.chosenProductId} />; } productChanged(productId) { this.setState({ chosenProductId: productId }); } } export default OrdersTab;
import React from 'react'; import { SelectBox } from 'devextreme-react/select-box'; import { createStore } from 'devextreme-aspnet-data-nojquery'; const url = 'https://js.devexpress.com/Demos/Mvc/api/DataGridAdvancedMasterDetailView'; class ProductSelectBox extends React.Component { constructor(props) { super(props); this.productsData = createStore({ key: 'ProductID', loadParams: { SupplierID: this.props.supplierId }, loadUrl: `${url}/GetProductsBySupplier`, onLoaded: this.setDefaultValue.bind(this) }); this.valueChanged = this.valueChanged.bind(this); } render() { return ( <SelectBox value={this.props.productId} deferRendering={false} dataSource={this.productsData} valueExpr={'ProductID'} displayExpr={'ProductName'} onValueChanged={this.valueChanged} /> ); } setDefaultValue(items) { let firstItem = items[0]; if(firstItem && this.props.productId === null) { this.props.onProductChanged(firstItem.ProductID); } } valueChanged(e) { this.props.onProductChanged(e.value); } } export default ProductSelectBox;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render( <App />, document.getElementById('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/19.1.7/css/dx.common.css" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/19.1.7/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.4.1/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.js'); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></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; }
System.config({ transpiler: 'plugin-babel', paths: { 'npm:': 'https://unpkg.com/' }, defaultExtension: 'js', meta: { 'devextreme-aspnet-data-nojquery': { 'esModule': true } }, map: { 'react': 'npm:react@16/umd/react.development.js', 'react-dom': 'npm:react-dom@16/umd/react-dom.development.js', 'prop-types': 'npm:prop-types/prop-types.js', 'devextreme': 'npm:devextreme@19.2', 'devextreme-react': 'npm:devextreme-react@19.2', 'jszip': 'npm:jszip@3.1.3/dist/jszip.min.js', 'quill': 'npm:quill@1.3.7/dist/quill.js', 'devexpress-diagram': 'npm:devexpress-diagram', 'devexpress-gantt': 'npm:devexpress-gantt', 'devextreme-aspnet-data-nojquery': 'npm:devextreme-aspnet-data-nojquery@2.5.1', // SystemJS plugins 'plugin-babel': 'npm:systemjs-plugin-babel@0/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0/systemjs-babel-browser.js' }, packages: { 'devextreme': { defaultExtension: 'js' }, 'devextreme-react': { main: 'index.js' } }, babelOptions: { sourceMaps: false, stage0: true, react: true } });