How to pass a function main component to columns array in Tank Stack Table 8 @tanstack/react-table
#5312
-
How to pass a function main component to the columns array of objects in Tank Stack Table @tanstack/react-table. I have a function Is there a way or method to handle the problem??
"use client";
import * as React from "react";
import { CaretSortIcon } from "@radix-ui/react-icons";
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
const data: Payment[] = [
{
id: "m5gr84i9",
amount: 316,
status: "success",
email: "ken99@yahoo.com",
},
{
id: "3u1reuv4",
amount: 242,
status: "success",
email: "Abe45@gmail.com",
},
{
id: "derv1ws0",
amount: 837,
status: "processing",
email: "Monserrat44@gmail.com",
},
{
id: "5kma53ae",
amount: 874,
status: "success",
email: "Silas22@gmail.com",
},
{
id: "bhqecj4p",
amount: 721,
status: "failed",
email: "carmella@hotmail.com",
},
];
export type Payment = {
id: string;
amount: number;
status: "pending" | "processing" | "success" | "failed";
email: string;
};
/**
* @description - I want to get the handleDelete function from the DataTable component and call it on the delete button in the action columns
*/
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => (
<div className="capitalize">{row.getValue("status")}</div>
),
},
{
accessorKey: "email",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Email
<CaretSortIcon className="ml-2 h-4 w-4" />
</Button>
);
},
cell: ({ row }) => <div className="lowercase">{row.getValue("email")}</div>,
},
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const payment = row.original;
return (
<Button
variant="destructive"
/**
* @description - I want to call this `handleDelete` function to the delete button press below
*/
// onClick={() => handleDelete(payment.id)}
>
Delete
</Button>
);
},
},
];
export default function DataTable() {
const [tableData, setTableData] = React.useState<Payment[]>([]);
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
});
/**
* @description - I want to pass this function to the delete button in the action columns
* @param id delete byn id
*/
const handleDelete = (id: string) => {
// delete the row with the id
data.filter((item) => item.id !== id);
};
React.useEffect(() => {}, []);
return (
<div className="w-full">
<h2 className="text-2xl font-bold text-center my-4">Tank Stack Table</h2>
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="space-x-2">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
</div>
);
} |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 13 replies
-
You can use meta for that |
Beta Was this translation helpful? Give feedback.
-
It is really works. Thanks |
Beta Was this translation helpful? Give feedback.
-
Other than meta, you can also use a function callback to generate your columns. E.g, export const getColumns = ({ onDelete }: { onDelete: (id: string) => void }): ColumnDef<Payment>[] => [
// ...
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const payment = row.original;
return (
<Button
variant="destructive"
onClick={() => onDelete(payment.id)}
>
Delete
</Button>
);
},
},
];
export default function DataTable() {
// ...
const handleDelete = useCallback((id: string) => {
// ...
}, []);
const columns = useMemo(() => getColumns({ onDelete: handleDelete }), [handleDelete]);
const table = useReactTable({
columns,
// ...
});
// ...
return (
// ...
);
} I avoid using meta because meta's typing is globally available, which many cases might not be as ideal because the callback could be specific to only certain tables. E.g, Updated 2024 Oct 29 Nowadays, I usually define meta to be more specific to the table that I am building. E.g, for a transaction table with declare module '@tanstack/react-table' {
interface TableMeta<TData extends RowData> {
onTransactionReject?: (context: CellContext<TData, unknown>) => void;
onTransactionApprove?: (context: CellContext<TData, unknown>) => void;
}
}
const columnHelper = createColumnHelper<Transaction>();
export const columns = [
// ...
columnHelper.display({
id: 'actions',
cell: (context) => (
<div className="flex justify-end gap-2">
<Button
variant="destructive"
onClick={() =>
context.table.options.meta?.onTransactionReject?.(context)
}
// ...
>
Reject
</Button>
<Button
onClick={() =>
context.table.options.meta?.onTransactionApprove?.(context)
}
// ...
>
Approve
</Button>
</div>
),
}),
];
export default function DataTable() {
// ...
const table = useReactTable({
columns,
meta: {
onTransactionApprove: React.useCallback((context: CellContext<Transaction, unknown>) => {
// ...
}, []),
onTransactionReject: React.useCallback((context: CellContext<Transaction, unknown>) => {
// ...
}, []),
},
// ...
});
// ...
return (
// ...
);
} Instead of an
|
Beta Was this translation helpful? Give feedback.
You can use meta for that
https://tanstack.com/table/v8/docs/api/core/table#meta