Master-Detail React DataGrid with Charts

RMAG news

In this article, I want to show you how easy it is to leverage the master-detail support in the Infinite Table React DataGrid in order to toggle between a table and a chart view in the row detail.

In the RowDetail component of Infinite Table, we render a <DataSource />, which in turn will render either an <InfiniteTable /> component or a chart.

The <DataSource /> in InfiniteTable is very powerful and does all the data processing the grid needs. All the row grouping, sorting, filtering, aggregations, pivoting are done in the <DataSource /> – so you can use it standalone, or with InfiniteTable – it’s totally up to you.

In practice, this means that you can use the <DataSource /> to process your data and then simply pass that to a charting library like ag-charts-react.

const detailGroupBy: DataSourcePropGroupBy<Developer> = [{ field: stack }];
const detailAggregationReducers: DataSourcePropAggregationReducers<Developer> =
{
salary: {
field: salary,
initialValue: 0,
reducer: (acc, value) => acc + value,
done: (value, arr) => Math.round(arr.length ? value / arr.length : 0),
},
};

function RowDetail() {
const rowInfo = useMasterRowInfo<City>()!;
const [showChart, setShowChart] = React.useState(rowInfo.id % 2 == 1);

return (
<div style={{…}}>
<button onClick={() => setShowChart((showChart) => !showChart)}>
Click to see {showChart ? grid : chart}
</button>

{/**
* In this example, we leverage the DataSource aggregation and grouping feature to
* calculate the average salary by stack for the selected city.
*/
}
<DataSource<Developer>
data={detailDataSource}
primaryKey=id
groupBy={detailGroupBy}
aggregationReducers={detailAggregationReducers}
>
{/**
* Notice here we’re not rendering an InfiniteTable component
* but rather we use a render function to access the aggregated data.
*/
}
{(params) => {
// here we decide if we need to show the chart or the grid
if (!showChart) {
return (
<InfiniteTable
columns={detailColumns}
domProps={{
style: { paddingTop: 30 },
}}
/>
);
}

// the dataArray has all the aggregations and groupings done for us,
// so we need to retrieve the correct rows and pass it to the charting library
const groups = params.dataArray.filter((rowInfo) => rowInfo.isGroupRow);
const groupData = groups.map((group) => ({ stack: group.data?.stack, avgSalary: group.reducerData?.salary }));

return (
<AgChartsReact
options={{
autoSize: true,
title: {
text: `Avg salary by stack in ${rowInfo.data?.name}, ${rowInfo.data?.country}`,
},
data: groupData,
series: [
{
type: bar,
xKey: stack,
yKey: avgSalary,
yName: Average Salary,
},
],
}}
/>
);
}}
</DataSource>
</div>
);
}

The demo above is using the ag-charts-react package to render the charts.

Read more about the rendering custom content in a master-detail setup.

Leave a Reply

Your email address will not be published. Required fields are marked *