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.
-
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