Reputation: 53
I'm working on creating a table component using NextJS and TanStack Table. Currently, I have a component that serves as the foundation for the TanStack Table. I pass the respective ColumnDef of the page and the data to be displayed into this component. In other words, depending on the page I visit, different data is fed into the TanStack Table.
This is working well so far. Now, I want to include a method for an onClick event for each page. For example, Page 1 should receive onRowClicked1, and Page 2 should receive onRowClicked2.
Whats the best way of doing it? I tried to pass the function from the parent component to the TableComponent but is this the best way?
Thanks!
This is my TableComponent:
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import React, { useState } from "react";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
const table = useReactTable({
data,
columns,
state: {
sorting,
columnFilters,
columnVisibility,
},
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
return (
<>
<div className="rounded-md border">
<table className="border border-gray-700 w-full text-left">
<thead className="bg-indigo-600">
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id} className="capitalize px-3.5 py-2">
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row, i) => (
<tr
key={row.id}
className={`
${i % 2 === 0 ? "bg-gray-900" : "bg-gray-800"}
`}
>
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className="px-3.5 py-2" onClick={() => console.log(row.original.id)}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
))}
</tr>
))
) : (
<tr className="text-center h-32">
<td colSpan={12}>No Recoard Found!</td>
</tr>
)}
</tbody>
</table>
</div>
</>
);
}
Upvotes: 4
Views: 1153
Reputation: 69
I have a similar implementation, although I'm looking for a solution to more closely expose my click event (per column vs per row) here.
Passing it to the row specifically, as you've done, seems to be the most powerful way (so far), as it makes the entire row/cell space clickable for that specific action, and you can pass the row value to it for manipulation.
The alternative that I know of is altering your column definition so that the click event is specific to that column value, but the drawback is that it is only clickable when your mouse is over the content of the cell, rather than the entire cell space. Here is my example implementation of that:
{ cell: ({row}) => <div onClick={() => openAction('View', row.original)}>{row.original.name}</div>, accessorKey: 'name', minSize: 200, header: 'Name', enableMultiSort: true },
As long as you specify the accessorKey
, your values are sortable (if sorting is enabled).
I just realized that switching from span
to div
makes the entire cell space clickable, so I'm moving forward with that on my project.
Upvotes: 3