I am using Grouping in material table. In the group view when I try to add a new row , it doesn't show grouped column.
In following example , I am doing column grouping based on "Geography" column. In the grouped view when I try to "Add" new records ,I don't see Geography field. However when I remove all grouping , it works as expected.
import React from "react";
import MaterialTable, { MTableToolbar } from "material-table";
export default function MatTableDemo() {
const columns = [
{ title: "Geography", field: "geo", defaultGroupOrder: 0, editable: "onAdd" },
{ title: "Prouct Category", field: "prodCat", editable: "onAdd" },
{ title: "Items", field: "item", grouping: false, editable: "onAdd" },
];
const data = [
{
id: 1,
geo: "Canada",
prodCat: "Food",
item: "Dairy",
},
{
id: 2,
geo: "Europe",
prodCat: "Food",
item: "Dairy",
},
];
return (
<MaterialTable
title="Grouped Table"
columns={columns}
data={data}
editable={{
onRowAdd: (newData) => {
return new Promise((resolve) => {
//handleRowAdd(newData, resolve)
})
},
}}
options={{
grouping: true,
paging: false,
}}
/>
)
}
I'm not aware of an easy way to achieve what you are looking for, also I found a few closed or stall issues regarding this behavior on the official repository (link1 or link2).
Based on the Duplicate Action Preview example at the docs, I found two different workarounds, boths using tableRef
and initialFormData
props.
I defined a custom action
that allows removing the applied filters before presenting the addition row. This is done by performing a re-rendering from setting a different initialFormData
value.
actions={[
{
icon: "library_add",
tooltip: "Create User",
onClick: (event, rowData) => {
const materialTable = tableRef.current;
setInitialFormData({});
materialTable.setState({
...materialTable.dataManager.getRenderState(),
showAddRow: true
});
}
}
]}
This works without using defaultGroupOrder
on column definition and requires at least one column with a render
prop defined.
const tableColumns = [
{
title: "Category", field: "category"
},
{ title: "Name", field: "name" },
{
title: "Password",
field: "password",
grouping: false,
render: (rowData) => (
<input type="password" value={rowData.password} readOnly />
)
}
];
The same approach as before, but initialFormData
now may take the value of the category (is taken from rowData
), so when the addRow is rendered, the field is not shown but the value is set.
actions={[
{
icon: "library_add",
tooltip: "Create User",
onClick: (event, rowData) => {
const materialTable = tableRef.current;
setInitialFormData({
category: rowData.category // 2nd approach
});
materialTable.setState({
...materialTable.dataManager.getRenderState(),
showAddRow: true
});
}
}
]}
Works with the defaultGroupOrder
on column definition:
const tableColumns = [
{
title: "Category",
field: "category",
defaultGroupOrder: 0 // 2nd approach
},
{ title: "Name", field: "name" },
{
title: "Password",
field: "password",
grouping: false,
render: (rowData) => (
<input type="password" value={rowData.password} readOnly />
)
}
];
The second approach may look better but it's a bit tricky for the user since the addRow always spawns as the 'last' or 'first' row of the table.
To avoid rendering the default **add action button ** on the top right of the table, I use a custom action component to overwrite it, like this:
components={{
Action: (props) => {
//If isn't the add action
if (
typeof props.action === typeof Function ||
props.action.tooltip !== "Add"
) {
return <MTableAction {...props} />;
} else {
return <></>;
}
}
}}
Definitely, this solution feels a little bit hacky, but as I said before I think they are workarounds until the feature is included on the main component. Hopefully, someone can improve over these proposals.
Hope that works for you! Sandbox here.