Search code examples
javascriptreactjstypescriptmaterial-uimui-x-data-grid

How do I use the current MUI state to sum and display columns?


I have an MUI webapp I'm creating to track some personal data.

I am using MUI datagrid pro to display the data, and as we know, it has some pretty extensive filters within the datagrid component.

I would like to display summated totals of the currently displayed filtered columns, rather than having to requery the database to get those specific values. It feels like it should be fairly straightforward, but I'm not sure how to access it.

The datagridpro API is here: https://mui.com/x/api/data-grid/data-grid-pro/

My datagrid component is constructed like so:

const fetchData = useCallback(
    async (IDs: string[]) => { 
        response = await fetch("/api/data")
        data = response.json()
        ...
        ...
        ... 


        transformedData = transformData(data)

        return { data: transformedData }, }; 
     [dispatch] );

This gets fed through a standard useEffect to set the state with the data.

And the transformedData method resembles this:

const transformedData = (data: any) => {
   return data.map((item: any, index: any) => {
  const timestamp = new Date(item.timestamp)

  return {
    id: item.id
    value_1: item.value_1
    value_2: item.value_2
    date: timestamp
    value_3: item.value_3
   };
});
};

This is the current code displaying the DataGridPro component:

<DataGridPro
    rows={transformedDataFromFunction}
    sx={{
      ".MuiDataGrid-row:hover": {
        backgroundColor: "#C2C2C2",
      },
    }}
    columns={columns}
    editMode="row"
    rowModesModel={rowModesModel}
    onRowModesModelChange={(newModel: typeof rowModesModel) =>
      setRowModesModel(newModel)
    }
    onRowEditStart={handleRowEditStart}
    onRowEditStop={handleRowEditStop}
    processRowUpdate={processRowUpdate}
    componentsProps={{
      toolbar: { setRowModesModel },
    }}
    slots={{ toolbar: GridToolbar }}

    // leaving this in here on off chance we don't need MUI
    // experimentalFeatures={{ newEditingApi: true }}
  />

Again, I essentially want to display the summated totals of specified columns in a separate div at the top of the page, in the form:

Total Val 1: sum(value_1) | Total Val 2: sum(value_2) | Total #: sum(index)


[insert table data here]

Again, when I filter based on the MUI datagrid, I'd like to display the summated totals of those displayed columns.

Let's say value_1 has 4 rows total with values displayed below

    value_1 
   |   3     
   |   4
   |   1
   |   2

Let's say I want to filter by values >2.

On the datagridpro component, this would be filtered and displayed as this:

    value_1 
   |   3     
   |   4

I want to show the count of columns displayed, which would be 2, and the sum of the rows would be 7.

What API prop(s) should I use to access this?

Thank you


Solution

  • You can use the gridFilteredSortedRowIdsSelector from the MUI DataGridPro API to get the summated totals of the columns. This selector returns an array of row ids that are currently filtered and sorted in the grid. You can use this array to access the rows' data and calculate the summated totals of the columns you want. For example, you can do something like this:

    const SummatedTotals = () => {
      const apiRef = useGridApiContext();
      const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
    
      const filteredSortedRows = filteredSortedRowIds.map((id) =>
        apiRef.current.getRow(id)
      );
    
      const totalUnitPrice = filteredSortedRows.reduce(
        (sum, row) => sum + row.unitPrice,
        0
      );
      const totalFeeRate = filteredSortedRows.reduce(
        (sum, row) => sum + row.feeRate,
        0
      );
      const totalCount = filteredSortedRows.length;
    
      return (
        <div>
          {`Total Unit Price: ${
            Math.round(totalUnitPrice * 100) / 100
          } | Total Fee Rate: ${
            Math.round(totalFeeRate * 100) / 100
          } | Total #: ${totalCount}`}
        </div>
      );
    };
    

    And then

    <DataGridPro
      /* { ...restProps } */
      slots={{ footer: SummatedTotals }}
    />
    

    You can see the whole example here: codesandbox.io

    To learn more, please see Filtering Selectors, API Object, and Access The State.