different TypeScript types for subRows #4484
Replies: 7 comments 3 replies
-
Hey mate, I had issues with this but found a nice solution. Basically you need to create a new table for the inner arrays and then you can use the manual expanding option. The code below uses tailwind for css: import type { ColumnDef } from "@tanstack/react-table";
import { flexRender } from "@tanstack/react-table";
import { getCoreRowModel, getExpandedRowModel, useReactTable } from "@tanstack/react-table";
import React from "react";
type Project = {
_type: "Project";
title: string;
dueDate: Date;
tasks?: Task[];
};
type Task = {
_type: "Task";
title: string;
status: "Waiting" | "In Progress" | "Urgent" | "On Hold" | "Done";
assignee: string;
};
const ExampleTableWithSubRows: React.FC<{ projects: Project[] }> = ({ projects }) => {
const columns = React.useMemo<ColumnDef<Project>[]>(
() => [
{
header: "Title",
accessorKey: "title",
cell: ({ getValue, row }) => {
return (
<div className="flex gap-2">
{row.getCanExpand() && (
<span
className={`h-4 w-4 transition-transform ${
row.getIsExpanded() ? "rotate-90" : "rotate-0"
}`}
>
{">"}
</span>
)}{" "}
{getValue() as string}
</div>
);
},
},
{ header: "dueDate", accessorKey: "dueDate" },
],
[],
);
const headlessTable = useReactTable({
data: projects || [],
columns,
getCoreRowModel: getCoreRowModel(),
getExpandedRowModel: getExpandedRowModel(),
enableExpanding: true,
getRowCanExpand: (row) => !!row.original?.tasks?.length, // check if the sub rows can expand
});
return (
<table className="w-full">
<thead>
{headlessTable.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th
key={header.id}
className={
"whitespace-nowrap border-b border-gray-400 p-3 text-left text-xs font-semibold"
}
>
{flexRender(header.column.columnDef.header, header.getContext())}
</th>
);
})}
</tr>
))}
</thead>
<tbody className="divide-y divide-gray-200 bg-white text-xs">
{headlessTable.getRowModel().rows.map((row) => {
return (
<>
<tr
key={row.id}
{...(row.getCanExpand() && {
onClick: row.getToggleExpandedHandler(),
style: { cursor: "pointer" },
})}
>
{row.getVisibleCells().map((cell) => {
return (
<td
key={cell.id}
className={"justify-center whitespace-nowrap p-3 text-left align-middle"}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
);
})}
</tr>
{row.original.tasks && row.getIsExpanded() && (
<tr key={row.id + "expansion"}>
<td colSpan={row.getVisibleCells().length} className="px-5">
<SubTable tasks={row.original.tasks} />
</td>
</tr>
)}
</>
);
})}
</tbody>
</table>
);
};
const SubTable: React.FC<{ tasks: Task[] }> = ({ tasks }) => {
const columns = React.useMemo<ColumnDef<Task>[]>(
() => [
{ header: "Title", accessorKey: "title" },
{ header: "Assignee", accessorKey: "assignee" },
{ header: "Status", accessorKey: "status" },
{ header: "Type", accessorKey: "_type" },
],
[],
);
const headlessTable = useReactTable({
data: tasks || [],
columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<table className="w-full">
<thead>
{headlessTable.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th key={header.id} className={"whitespace-nowrap p-3 text-left text-xs font-semibold"}>
{flexRender(header.column.columnDef.header, header.getContext())}
</th>
);
})}
</tr>
))}
</thead>
<tbody className="divide-y divide-gray-200 text-xs">
{headlessTable.getRowModel().rows.map((row) => {
return (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<td key={cell.id} className={"whitespace-nowrap p-3 text-left"}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
);
};
export default () => {
return (
<ExampleTableWithSubRows
projects={[
{
_type: "Project",
dueDate: new Date(),
title: "Example sub rows",
tasks: [{ _type: "Task", assignee: "Ligma", status: "In Progress", title: "TODO" }],
},
{ _type: "Project", dueDate: new Date(), title: "Example sub rows" },
]}
/>
);
};
|
Beta Was this translation helpful? Give feedback.
-
Is there a better solution yet? |
Beta Was this translation helpful? Give feedback.
-
any solution for this? |
Beta Was this translation helpful? Give feedback.
-
It's not a definite solution, but we can fake-cast the type to bypass the typescript error.
unless you need to call getSubRows to get the |
Beta Was this translation helpful? Give feedback.
-
My solution so far is a union type for the table data, and then a type guard every time I access the data in columns or subRows: export type TableItem = ItemGroup | LineItem | SubItem;
const columns = useMemo<MRT_ColumnDef<TableItem>[]>(() => [
{
header: "Name",
accessorFn(row: TableItem) {
//...
if (isLineItem(row) || isItemGroup(row)) {
color = "primary";
} else {
color = "secondary";
}
//...
},
},
]);
const tableOptions = {
///...
columns,
getSubRows: (row: TableItem) => {
if (isItemGroup(row)) {
return row.lineItems || undefined;
}
if (isLineItem(row)) {
return row.subItems || undefined;
}
if (isSubItem(row)) {
return undefined;
}
},
//...
};
|
Beta Was this translation helpful? Give feedback.
-
I'm using the shadcn/ui table example. And I've solved the problem by using the "any" option: The code of the table: interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
pathSubRows?: string;
}
export function DataTable<TData, TValue>({
columns,
data,
pathSubRows,
}: DataTableProps<TData, TValue>) {
const [expanded, setExpanded] = useState<ExpandedState>({});
const table = useReactTable({
data,
columns,
state: {
expanded,
},
getCoreRowModel: getCoreRowModel(),
onExpandedChange: setExpanded,
getSubRows: pathSubRows ? (row: any) => row[pathSubRows] : undefined,
getExpandedRowModel: getExpandedRowModel(),
});
//.... What's it called: <DataTable columns={columns}
data={userOrders}
pathSubRows="tasks"
/> |
Beta Was this translation helpful? Give feedback.
-
Is there a better solution yet? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
How can I declare a different Data type for subRows ? All the examples I have seen use the same type for nested subrows.
In my case I have Projects (parent) which have 1 or more Tasks (children aka subRows).
and my data type is
Project[]
When i declare the React Table using Project as the generic type ...
... I get a TypeScript error when defining
getSubRows
:Beta Was this translation helpful? Give feedback.
All reactions