Sending functions as props to Shadcn UI Table

61 Views Asked by At

I am using a Data Table from Shadcn in a React project with Typescript. I wanted to an Actions menu with a Dropdown list as listed in the example.

"use client";

import { ColumnDef } from "@tanstack/react-table";
import { MoreHorizontal } from "lucide-react";
import { dataRowRow } from "../../common/Types";

import { Button } from "../ui/button";
import "./Columns.css";

import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuLabel,
    DropdownMenuSeparator,
    DropdownMenuTrigger,
} from "../ui/dropdown-menu";

export const columns: ColumnDef<dataRowRow>[] = [
    {
        accessorKey: "locationName",
        header: "Location",
    },
    {
        accessorKey: "status",
        header: "Status",
    },

    {
        id: "actions",
        header: "Actions",
        cell: ({ row }) => {
            const dataRow = row.original;

            return (
                <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                        <Button variant="ghost" className="h-8 w-8 p-0">
                            <span className="sr-only">Open menu</span>
                            <MoreHorizontal className="h-4 w-4" />
                        </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                        <DropdownMenuLabel>Actions</DropdownMenuLabel>
                        <DropdownMenuItem onClick={() => console.log(dataRow)}>
                            Edit dataRow
                        </DropdownMenuItem>
                        <DropdownMenuItem>Delete dataRow</DropdownMenuItem>
                        <DropdownMenuItem>Generate URL</DropdownMenuItem>
                        <DropdownMenuSeparator />
                        <DropdownMenuItem
                            onClick={() =>
                                navigator.clipboard.writeText(dataRow.url)
                            }
                        >
                            Copy upload URL
                        </DropdownMenuItem>
                    </DropdownMenuContent>
                </DropdownMenu>
            );
        },
    },
];

The copy to clipboard function works without a hitch. However, how could I send another function as a parameter to the component to manage for example the deletion of a row?

Like saving the row in a state and opening a modal that manages the API call for example?

1

There are 1 best solutions below

0
Mahmoud Elshazly On

you have data row so you can do all you want

some examples

Delete

const onDelete = async (id) => {
// call your api endpoint use fetch, axios or server action
    try {
        // with axios
        await axios.delete('your-api/endpoint/'+ id)
        // or with fetch  await fetch('your-api/endpoint/'+ id, {method: 'DELETE'});
        // or with server action await deleteServerFn(id);
        // handel success 
    } catch (error) {
        // handel error
    }
}

<DropdownMenuItem onClick={onDelete(dataRow.id)}>
   Delete this row
</DropdownMenuItem>

Edit

To edit you need a state management library to control the modal I will explain to you using Zustand, You can use whatever you prefer

1- create a store

export const useEditModal = create((set) => ({
    dataRow: null,
    isOpen:false,
    openEditModal:(data)=> set({isOpen:true,dataRow:data}),
    onClose:()=> set({isOpen:false,dataRow:null})
}))

we need data row to display in form

2- create modal and control it by store

i use shadcn Dialog, again You can use whatever you prefer

const {isOpen,dataRow,onEditClose} = useEditModal()
...
<Dialog open={isOpen} onOpenChange={onEditClose} >
//  delete DialogTrigger  Because we will control it using isOpen
    ...
</Dialog>

3- add onClickto DropdownMenu action

const {openEditModal} = useEditModal()

<DropdownMenuItem onClick={() => openEditModal(payment) }>
    Edit this row
</DropdownMenuItem>

4- build your form in Dialog

check for https://ui.shadcn.com/docs/components/form

There is one thing different instead of putting an empty values in defaultValues put the dataRow values

    defaultValues: {
      username: dataRow.username,
      ...
    },

now you can call your api endpoint onSubmit and update row with formValues

 function onSubmit(formValues: z.infer<typeof formSchema>) {
     // call your api endpoint 
  try {
        axios.put(`your-api/endpoint/'+ dataRow.id`, formValues)
        // handel success 
    } catch (error) {
        // handel error
    }
  }