1

I am running into a bit of a problem grabbing data from a Data Grid (or XGrid) to display in another component on the page.

From the code below you can see that I am grabbing data from a local database that I am displaying in a Data Grid. What I want to do now is add the ability to take the selected rows and display the data (product ID, description, price, etc.) and display it in another component. Right now, I will settle for just a single selection.

I have tried many suggestions found here to add a onSelectionModelChange, but the only thing I am able to grab is the row id value. Not that it would make that much difference, but I am using MySQL for the backend.

Any suggestions?

Here's my React file:

import * as React from 'react';
import Axios from 'axios';
import { Grid } from '@material-ui/core';

import { createTheme } from '@material-ui/core/styles';
import { makeStyles } from '@material-ui/styles';
import { GridToolbarDensitySelector, GridToolbarFilterButton, XGrid } from '@material-ui/x-grid';

const currencyFormatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
});

const usdPrice = {
    type: 'number',
    width: 180,
    valueFormatter: ({ value }) => currencyFormatter.format(Number(value)),
    cellClassName: 'font-tabular-nums',
};

const defaultTheme = createTheme();
const useStyles = makeStyles(
    (theme) => ({
        root: {
            padding: theme.spacing(0.5, 0.5, 0),
            justifyContent: 'space-between',
            display: 'flex',
            alignItems: 'flex-start',
            flexWrap: 'wrap',
            background: '#f3f5f6'
        },
        textField: {
            [theme.breakpoints.down('xs')]: {
                width: '100%',
            },
            margin: theme.spacing(1, 0.5, 1.5),
            '& .MuiSvgIcon-root': {
                marginRight: theme.spacing(0.5),
            },
            '& .MuiInput-underline:before': {
                borderBottom: `1px solid ${theme.palette.divider}`,
            },
        },
    }),
    { defaultTheme },
);

function FilteringToolbar() {
    const classes = useStyles();

    return (
        <div className={classes.root}>
            <div>
                <GridToolbarFilterButton />
                <GridToolbarDensitySelector />
            </div>
        </div>
    );
}

const ProductTable = () => {

    const [rowData, setRowData] = React.useState([]);
    const [rows, setRows] = React.useState(rowData);

    React.useEffect(() => {
        const axios = require('axios').default;
        Axios.get("http://localhost:3001/api/get").then((response) => {
            setRows(response.data);
        }).catch(e => {
            window.alert(e);
        });
    }, [rowData]);

    const columns = [
        { field: 'prodID', headerName: 'Product ID', width: 130, disableReorder: true } ,
        { field: 'desc', headerName: 'Description', width: 200, editable: true, disableReorder: true },
        { field: 'price', headerName: 'Price', editable: true, disableReorder: true, ...usdPrice },
        { field: 'inStock', headerName: 'In Stock', width: 110, editable: true, disableReorder: true, headerAlign: 'center', align: 'center', type: 'boolean'},
        { field: 'new', headerName: 'New', width: 110, editable: true, disableReorder: true, headerAlign: 'center', align: 'center', type: 'boolean' },
    ]

    return (
        <Grid container item xs={12}>
            <Grid container item xs={12}>
                <Grid container item xs={3} />
                <Grid container item xs={6} justifyContent="center" alignItems="center">
                <div style={{ height: 500, width: '100%', display: 'block', marginLeft: 'auto', marginRight: 'auto' }}>
                    <XGrid checkboxSelection {...rows}
                        components={{ Toolbar: FilteringToolbar }}
                        rows={rows}
                        columns={columns}
                        id="id"
                    />
            </div>
            </Grid>
            <Grid container item xs={3} />
            </Grid>
        </Grid>
    );
}

export default ProductTable;

1 Answer 1

1
+50

I would suggest that instead of trying to get the row data that you need to pass to any child/related components from the table, you get the data directly from your own component's state. Since you already have the ids returned from onSelectionModelChange, you can simply use them to filter the rows state to get the selected items. For example:

...

const [selected, setSelected] = React.useState([]);
const [rows, setRows] = React.useState([]);

const handleSelectionChange = React.useCallback(
  (selected = []) => {
    setSelected(rows.filter(({ prodID }) => selected.includes(prodID)));
  },
  [rows] 
);

...
<XGrid
  // Calls our handler function that filters the selected items from state
  onSelectionModelChange={handleSelectionChange}
  checkboxSelection
  {...rows}
  components={{ Toolbar: FilteringToolbar }}
  rows={rows}
  columns={columns}
  // Re-wires the grid to use your `prodID` instead of it's default `id`
  getRowId={({ prodID }) => prodID}
/>

Demo Example

Working Code Sandbox: https://codesandbox.io/s/datagrid-selected-items-rm3f1?file=/src/App.tsx

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! This looks great. I will wait for other answers but if none are provided, I will award you the bounty for this question.
Thanks @hfontanez -- let me know if you need any additional clarity on the what I'm doing here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.