The sheet closes upon submission even when there’s an error. I’m unsure where to place the error trap in the code to prevent the sheet from closing.
I found a post to prevent that from happening
Prevent closing of shadcn Sheet component based on a certain condition
When I change the suggested tag from
<Sheet onOpenChange={() => setIsOpen(true)}>
to
<Sheet open={isOpen} onOpenChange={() => setIsOpen(true)}>
I am not able to close the sheet using top close or Cancel button
cellaction.txs
"use client";
import { CategoryForm } from "@/components/forms/category-form";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Sheet, SheetTrigger } from "@/components/ui/sheet"
import { Category } from "@/constants/data";
import { Edit, MoreHorizontal, Trash } from "lucide-react";
import { useState } from "react";
interface CellActionProps {
data: Category;
}
export const CellAction: React.FC<CellActionProps> = ({ data }) => {
const [open, setOpen] = useState(false);
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Sheet onOpenChange={() => setIsOpen(true)}>
<DropdownMenu modal={false}>
<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>
<SheetTrigger>
<div className="flex"><Edit className="mr-2 h-4 w-4"/>Edit</div>
</SheetTrigger>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setOpen(true)}>
<Trash className="mr-2 h-4 w-4" /> Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<CategoryForm initialData={data} setIsOpen={setIsOpen} isOpen={isOpen}/>
</Sheet>
</>
);
};
category-form.tsx
"use client";
import * as z from "zod";
import { useState } from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useParams, useRouter } from "next/navigation";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { useToast } from "../ui/use-toast";
import { SheetContent, SheetDescription, SheetHeader, SheetFooter, SheetTitle, SheetTrigger, SheetClose, } from "@/components/ui/sheet"
import React, { Dispatch, SetStateAction } from 'react'
const formSchema = z.object({
name: z
.string()
.min(3, { message: "Category Name must be at least 3 characters" }),
status: z.string().min(1, { message: "Please select a Status" }),
});
type CategoryFormValues = z.infer<typeof formSchema>;
interface CategoryFormProps {
initialData: any | null;
isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>
}
export const CategoryForm: React.FC<CategoryFormProps> = ({
initialData,
setIsOpen,
isOpen
}) => {
const params = useParams();
const router = useRouter();
const { toast } = useToast();
const [loading, setLoading] = useState(false);
const title = initialData ? "Edit product" : "Create product";
const description = initialData ? "Edit a product." : "Add a new product";
const toastMessage = initialData ? "Product updated." : "Product created.";
const action = initialData ? "Save changes" : "Create";
const defaultValues = initialData
? initialData
: {
name: "",
status: "",
};
const form = useForm<CategoryFormValues>({
resolver: zodResolver(formSchema),
defaultValues,
});
const onSubmit = async (data: CategoryFormValues, changeSetIsOpen: any) => {
try {
setLoading(true);
if (initialData) {
// await axios.post(`/api/categories/${initialData._id}`, data);
} else {
// const res = await axios.post(`/api/products/create-product`, data);
}
router.refresh();
/// Close Sheet
setIsOpen(false);
toast({
variant: "default",
title: toastMessage,
description: toastMessage
});
} catch (error: any) {
/// Keep Sheet open on error
setIsOpen(false);
toast({
variant: "destructive",
title: "Uh oh!! Something went wrong.",
description: "There was a problem with your request.",
});
} finally {
setLoading(false);
}
};
return (
<>
<SheetContent>
<SheetHeader>
<SheetTitle>{title}</SheetTitle>
<SheetDescription>
{description}
</SheetDescription>
</SheetHeader>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 w-full"
>
<div className="grid gap-4 py-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input
disabled={loading}
placeholder="Category name"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>Status</FormLabel>
<Select
disabled={loading}
onValueChange={field.onChange}
value={field.value}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger>
<SelectValue
defaultValue={field.value}
placeholder="Select a status"
/>
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem key="Active" value="Active">Active</SelectItem>
<SelectItem key="Inactive" value="Inactive">Inactive</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<SheetFooter>
<Button
onClick={() => setIsOpen(false)}
disabled={loading} className="ml-auto" type="submit">
{action}
</Button>
<SheetClose asChild>
<Button
onClick={() => setIsOpen(true)}
disabled={loading} className="ml-auto">
Cancel
</Button>
</SheetClose>
</SheetFooter>
</form>
</Form>
</SheetContent>
</>
)
}