Closed lfsaga closed 4 months ago
Do you have an index column to use? I remember having a similar issue at work and it turned out that it would need a unique index per row to handle the row expansion
for context we define the idAccessor
prop to be the id accessor. And in the rowExpansion
callback we define the content
function with the record and its index. IF we did not provide an idAccessor then it would open all rows.
Edit:
This is what I mean for idAccessor:
<DataTable
records={someRecords}
// define columns
columns={someColumns}
idAccessor={'important_unique_row_id_define_in_columns'} // This is important**
// execute this callback when a row is clicked
rowExpansion={{
allowMultiple: true,
content: ({ record, recordIndex }: any) => {
return <SomeComponent key={recordIndex} record={record} />;
},
}}
/>
Hi @mikkurogue,
I appreciate the recent fix. However, I've encountered a new challenge related to the row expanding logic in the component.
Context: In my current implementation, I'm not sending a unique ID for each element to the front end due to data modeling requirements. Instead, I use a combination of two fields (slug and version) as a composite index to ensure uniqueness.
Problem:
Question: Does this component support the declaration of a composed index? If not, how should I handle this situation where both slug and version together create a unique identifier for each row?
Looking forward to your guidance on this.
Thank you!
hey @lfsaga What you could do, is in your column definition create a hidden column that could be a combination of whatever 2 fields you want.
Something like this:
// Column definition
const cols = [
{
accessor: 'unique_row_id',
hidden: true
},
{
accessor: 'column_1',
title: 'Column 1',
}
]
and wherever you create your records array, you then have to create the composition value.
// data response from api as example
const dataFromApi = [
{
slug: 'route_slug',
version: 'v1',
column_1: 'Route slug v1'
},
{
slug: 'route_slug',
version: 'v2',
column_1: 'Route slug v2'
}
]
const records = dataFromApi.map((item) => {
return {
unique_row_id: `${item.slug}_${item.version}`, // note the composition here
column_1: item.column_1
}
})
And your datatable implementation would then have at least these 3 props:
<DataTable columns={columns} records={records} idAccessor={'unique_col_id'} />
As long as the combination of ${item.slug}_${item.version}
is always unique you should be fine. If this is not the case, I'd then recommend explicitly defining an index column in the same way and populating this from the Array.map(cb(element, index)
index and making sure indexes never overlap on the parent.
Edit: I do understand that this does create extra complexity and potential overhead as you have to create a new array to use, but this should be "doable" if your objects arent too big and you potentially fetch records by pagination.
Thank you so much @mikkurogue it's now fixed.
I ended up faking an ID field with the array index for each item and setting it as idAccessor
for the component.
Results:
import React, { useState, useEffect, useMemo } from 'react';
import { DataTable } from 'mantine-datatable';
export const PaginationDatatable = ({
columns,
data,
rowExpansion,
allowSelection = false,
pageSizes = [5, 10, 15]
}) => {
const [selectedRecords, setSelectedRecords] = useState([]);
const [pageSize, setPageSize] = useState(pageSizes[0]);
const [page, setPage] = useState(1);
const [records, setRecords] = useState([]);
useEffect(() => {
const from = (page - 1) * pageSize;
const to = Math.min(from + pageSize, data.length);
setRecords(data.slice(from, to).map((record, index) => ({ ...record, item_id: from + index + 1 })));
}, [data, page, pageSize]);
const columnsWithItemId = useMemo(() => [{ accessor: 'item_id', hidden: true }, ...columns], [columns]);
const dataTableProps = {
columns: columnsWithItemId,
records: records,
totalRecords: data.length,
recordsPerPage: pageSize,
page: page,
onPageChange: (newPage) => setPage(newPage),
recordsPerPageOptions: pageSizes,
onRecordsPerPageChange: (newPageSize) => {
setPageSize(newPageSize);
setPage(1);
},
idAccessor: 'item_id',
rowExpansion: rowExpansion,
paginationSize: 'xs'
};
if (allowSelection) {
dataTableProps.selectedRecords = selectedRecords;
dataTableProps.onSelectedRecordsChange = setSelectedRecords;
}
return (
<DataTable {...dataTableProps} />
);
};
Nice, cool stuff! Glad to be of service
Describe the bug IDK why my Next project turned into this bug, but the expanding rows official example it's expanding/collapsing all rows at same time, I had it working properly before but now it fails like this.
Expected behavior Expand a row at once.
Screenshots http://i.imgur.com/pPLeGvP.mp4
Desktop (please complete the following information):
"mantine-datatable": "^7.8.1"