I am using the material-table
package to display nested data tables (two levels of nesting) in a React app. Here is a simplified version of my nested table to provide context:
My database query returns the nested rows as JSON on each record. I pass the nested JSON object to the detailPanel
, where I render another <MaterialTable>
to display this data. Importantly, the nested data does not have the same column structure as the top-level data, so the parentChildData
Tree Data functionality isn't an option for me (if I'm mistaken, please show me how that would work for my case).
I need to be able to perform Create, Read, Update, and Delete on all records via my <MaterialTable>
s. I have Read, Update, and Delete working. The problem with Create is this:
The nested data (levels 2 and 3) are associated to their parent record by foreign key in my PostgreSQL database. I haven't found a way of getting the database ID of the parent record passed into the onRowAdd
function. The parent's ID is passed into the nested <MaterialTable>
as a hidden column, but the newData
object passed to onRowAdd
doesn't know the value of the parent.
A reproducible example is difficult, but here is some relevant, representative code:
<MaterialTable>
code:
<MaterialTable
icons={tableIcons}
title={'Level 1 Data'}
columns={Object.keys(data[0])
.filter(
(el) =>
![
'level_2_data',
'level_3_data',
].includes(el),
)
.map((el) => col_to_definition(el))}
data={data}
editable={edit_fns}
detailPanel={(rowData) => {
return (
rowData.level_2_data && (
<div
style={{
background: '#52b6e8',
padding: '10px 0px 10px 20px',
}}
>
{/* Level 2 Table */}
<MaterialTable
icons={tableIcons}
title={'Level 2 Data'}
columns={Object.keys(rowData.level_2_data[0])
.filter((el) => !['level_3_data'].includes(el))
.map((el) => col_to_definition(el))}
data={rowData.level_2_data}
editable={edit_fns}
detailPanel={(rowData) => {
return (
rowData.level_3_data && (
<div
style={{
background: '#d2ecf9',
padding: '10px 0px 10px 20px',
}}
>
{/* Level 3 Table */}
<MaterialTable
icons={tableIcons}
title={'Level 3 Data'}
columns={Object.keys(rowData.level_3_data[0])
.map((el) => col_to_definition(el))}
data={rowData.level_3_data}
editable={edit_fns}
/>
</div>
)
);
}}
/>
</div>
)
);
}}
/>
Edit Functions:
const edit_fns = {
isEditable: (rowData) => true,
isDeletable: (rowData) =>
!rowData.level_2_data || rowData.level_2_data.length === 0
? true
: false,
onRowAdd: async (newData) => {
const create_is_ok = createEntry('level_2', newData);
if (create_is_ok) set_fetch_trigger(fetch_trigger + 1);
},
onRowUpdate: async (newData) => {
const update_request_returned_ok = updateEntry('level_2', newData);
if (update_request_returned_ok) set_fetch_trigger(fetch_trigger + 1);
},
onRowDelete: async (oldData) => {
const delete_request_returned_ok = deleteEntry('level_2', oldData);
if (delete_request_returned_ok) set_fetch_trigger(fetch_trigger + 1);
return true;
},
};