diff --git a/docs/data/data-grid/master-detail/master-detail.md b/docs/data/data-grid/master-detail/master-detail.md index cb8614ff1114..d2366d51cdc0 100644 --- a/docs/data/data-grid/master-detail/master-detail.md +++ b/docs/data/data-grid/master-detail/master-detail.md @@ -189,6 +189,7 @@ More examples of how to customize the detail panel: - [One expanded detail panel at a time](/x/react-data-grid/row-recipes/#one-expanded-detail-panel-at-a-time) - [Expand or collapse all detail panels](/x/react-data-grid/row-recipes/#expand-or-collapse-all-detail-panels) +- [Toggling detail panels on row click](/x/react-data-grid/row-recipes/#toggling-detail-panels-on-row-click) ## apiRef diff --git a/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.js b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.js new file mode 100644 index 000000000000..3c9bdfd9c37e --- /dev/null +++ b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.js @@ -0,0 +1,194 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; +import Typography from '@mui/material/Typography'; +import Paper from '@mui/material/Paper'; +import Stack from '@mui/material/Stack'; +import { DataGridPro, useGridApiRef } from '@mui/x-data-grid-pro'; +import { + randomCreatedDate, + randomPrice, + randomCurrency, + randomCountry, + randomCity, + randomEmail, + randomInt, + randomAddress, + randomCommodity, +} from '@mui/x-data-grid-generator'; + +function DetailPanelContent({ row: rowProp }) { + return ( + + + + {`Order #${rowProp.id}`} + + + + Customer information + + {rowProp.customer} + {rowProp.email} + + + + Shipping address + + + {rowProp.address} + + + {`${rowProp.city}, ${rowProp.country.label}`} + + + + row.quantity * row.unitPrice, + }, + ]} + rows={rowProp.products} + sx={{ flex: 1 }} + hideFooter + /> + + + + ); +} + +const columns = [ + { field: 'id', headerName: 'Order ID' }, + { field: 'customer', headerName: 'Customer', width: 200 }, + { field: 'date', type: 'date', headerName: 'Placed at' }, + { field: 'currency', headerName: 'Currency' }, + { + field: 'total', + type: 'number', + headerName: 'Total', + valueGetter: (value, row) => { + const subtotal = row.products.reduce( + (acc, product) => product.unitPrice * product.quantity, + 0, + ); + const taxes = subtotal * 0.05; + return subtotal + taxes; + }, + }, +]; + +function generateProducts() { + const quantity = randomInt(1, 5); + return [...Array(quantity)].map((_, index) => ({ + id: index, + name: randomCommodity(), + quantity: randomInt(1, 5), + unitPrice: randomPrice(1, 1000), + })); +} + +const rows = [ + { + id: 1, + customer: 'Matheus', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 2, + customer: 'Olivier', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 3, + customer: 'Flavien', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 4, + customer: 'Danail', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 5, + customer: 'Alexandre', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, +]; + +export default function DetailPanelExpandOnRowClick() { + const getDetailPanelContent = React.useCallback( + ({ row }) => , + [], + ); + + const getDetailPanelHeight = React.useCallback(() => 400, []); + + const apiRef = useGridApiRef(); + + const onRowClick = React.useCallback( + (params) => { + apiRef.current.toggleDetailPanel(params.id); + }, + [apiRef], + ); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx new file mode 100644 index 000000000000..dc5df4e819e9 --- /dev/null +++ b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx @@ -0,0 +1,202 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; +import Typography from '@mui/material/Typography'; +import Paper from '@mui/material/Paper'; +import Stack from '@mui/material/Stack'; +import { + DataGridPro, + DataGridProProps, + GridColDef, + GridEventListener, + useGridApiRef, +} from '@mui/x-data-grid-pro'; +import { + randomCreatedDate, + randomPrice, + randomCurrency, + randomCountry, + randomCity, + randomEmail, + randomInt, + randomAddress, + randomCommodity, +} from '@mui/x-data-grid-generator'; + +function DetailPanelContent({ row: rowProp }: { row: Customer }) { + return ( + + + + {`Order #${rowProp.id}`} + + + + Customer information + + {rowProp.customer} + {rowProp.email} + + + + Shipping address + + + {rowProp.address} + + {`${rowProp.city}, ${rowProp.country.label}`} + + + row.quantity * row.unitPrice, + }, + ]} + rows={rowProp.products} + sx={{ flex: 1 }} + hideFooter + /> + + + + ); +} + +const columns: GridColDef<(typeof rows)[number]>[] = [ + { field: 'id', headerName: 'Order ID' }, + { field: 'customer', headerName: 'Customer', width: 200 }, + { field: 'date', type: 'date', headerName: 'Placed at' }, + { field: 'currency', headerName: 'Currency' }, + { + field: 'total', + type: 'number', + headerName: 'Total', + valueGetter: (value, row) => { + const subtotal = row.products.reduce( + (acc: number, product: any) => product.unitPrice * product.quantity, + 0, + ); + const taxes = subtotal * 0.05; + return subtotal + taxes; + }, + }, +]; + +function generateProducts() { + const quantity = randomInt(1, 5); + return [...Array(quantity)].map((_, index) => ({ + id: index, + name: randomCommodity(), + quantity: randomInt(1, 5), + unitPrice: randomPrice(1, 1000), + })); +} + +const rows = [ + { + id: 1, + customer: 'Matheus', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 2, + customer: 'Olivier', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 3, + customer: 'Flavien', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 4, + customer: 'Danail', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, + { + id: 5, + customer: 'Alexandre', + email: randomEmail(), + date: randomCreatedDate(), + address: randomAddress(), + country: randomCountry(), + city: randomCity(), + currency: randomCurrency(), + products: generateProducts(), + }, +]; + +type Customer = (typeof rows)[number]; + +export default function DetailPanelExpandOnRowClick() { + const getDetailPanelContent = React.useCallback< + NonNullable + >(({ row }) => , []); + + const getDetailPanelHeight = React.useCallback(() => 400, []); + + const apiRef = useGridApiRef(); + + const onRowClick = React.useCallback>( + (params) => { + apiRef.current.toggleDetailPanel(params.id); + }, + [apiRef], + ); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx.preview b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx.preview new file mode 100644 index 000000000000..db3ecef167cf --- /dev/null +++ b/docs/data/data-grid/row-recipes/DetailPanelExpandOnRowClick.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/row-recipes/row-recipes.md b/docs/data/data-grid/row-recipes/row-recipes.md index 6404572a316c..a21217ac8088 100644 --- a/docs/data/data-grid/row-recipes/row-recipes.md +++ b/docs/data/data-grid/row-recipes/row-recipes.md @@ -25,3 +25,9 @@ It checks the status of open panels using the [`useGridSelector` hook](/x/react- When clicked, it uses [`setExpandedDetailPanels`](/x/api/data-grid/grid-api/#grid-api-prop-setExpandedDetailPanels) from the [Grid API](/x/react-data-grid/api-object/#how-to-use-the-api-object) to expand or collapse all detail panels. {{"demo": "DetailPanelExpandCollapseAll.js", "bg": "inline", "defaultCodeOpen": false}} + +## Toggling detail panels on row click + +In the demo below, you can toggle the detail panel by clicking anywhere on the row: + +{{"demo": "DetailPanelExpandOnRowClick.js", "bg": "inline", "defaultCodeOpen": false}}