💬
【Convex】NextJs14 と Convex【#28 Convex Rename Form】
【#28 Convex Rename Form】
YouTube: https://youtu.be/yiZrdCjThl4
今回はモーダルにフォームを追加します。
フォームのデフォルトバリューの設定はいろいろやり方はあるのですが
今回はuseEffectを使ってさっくりと実装しています。
components/modals/rename-card-modal.tsx
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import {
Dialog,
DialogContent,
DialogHeader,
DialogDescription,
DialogClose,
DialogFooter,
DialogTitle,
} from "@/components/ui/dialog";
import { Form, FormControl, FormField } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { useRenameCardModal } from "@/store/use-rename-card-modal";
import { useApiMutation } from "@/hooks/use-api-mutation";
import { api } from "@/convex/_generated/api";
import { toast } from "sonner";
import { useEffect } from "react";
const formSchema = z.object({
title: z
.string()
.min(2, { message: "Title must be at least 2 characters." })
.max(50, { message: "Title must be less than 50 characters." }),
});
export const RenameCardModal = () => {
const { isOpen, onClose, initialValues } = useRenameCardModal();
const { pending, mutate } = useApiMutation(api.card.updateCard);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
title: "",
},
});
const onSubmit = (values: z.infer<typeof formSchema>) => {
mutate({
id: initialValues.id,
title: values.title,
})
.then(() => {
toast.success("Card updated");
onClose();
})
.catch((error) => {
toast.error("Failed to rename title");
console.log(error);
});
};
useEffect(() => {
form.setValue("title", initialValues.title);
}, [initialValues.title]);
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent>
<DialogHeader>
<DialogTitle>Rename card title</DialogTitle>
<DialogDescription>Enter a new card title.</DialogDescription>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="title"
render={({ field }) => <Input {...field} disabled={pending} />}
/>
<DialogFooter>
<DialogClose asChild>
<Button type="button" variant="outline">
Cancel
</Button>
</DialogClose>
<Button type="submit" disabled={pending}>
Save
</Button>
</DialogFooter>
</form>
</Form>
</DialogHeader>
</DialogContent>
</Dialog>
);
};
Discussion