i was trying react hook form with shadcn ui for my school projects and when i try to submit it, the onSubmit event doesnt do anything even when im trying to console log it.
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { useFetch } from "@/hooks/fetcher";
import { AttendanceSchema } from "@/schemas/attendance-schemas";
import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import React from "react";
import { useForm } from "react-hook-form";
import { useLocation } from "react-router-dom";
import { z } from "zod";
type StudentAttendanceType = {
nisn: string;
student_name: string;
};
const statuses = [ "Hadir", "Izin", "Sakit", "Alfa" ];
const Presensi = () => {
const [generatedId, setGeneratedId] = React.useState("");
const location = useLocation();
const scheduleId = location.pathname.split("/")[location.pathname.split("/").length - 1];
const { data } = useFetch<StudentAttendanceType[]>(
"http://localhost:8800/backend/attendances/getToAttend/" + scheduleId
);
const form = useForm<z.infer<typeof AttendanceSchema>>({
resolver: zodResolver(AttendanceSchema),
defaultValues: {
attendance_list_id: "123",
attendance: [
{
attendance_id: "123",
status: "Hadir",
student_id: "123",
description: "",
},
],
},
});
React.useEffect(() => {
const fetchData = async () => {
try {
const res = await axios.get(
"http://localhost:8800/backend/attendances/lastId/" + scheduleId
);
setGeneratedId(
parseInt(res.data[0].next_id).toString().padStart(3, "0")
);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [generatedId, scheduleId]);
React.useEffect(() => {
form.reset({
attendance: data.map((student) => ({
status: "Hadir",
student_id: student.student_name,
description: "",
})),
});
}, [form, data]);
const onSubmit = async (values: z.infer<typeof AttendanceSchema>) => {
try {
await axios.post("http://localhost:8800/backend/attendances/", {
attendance_list_id: scheduleId + "-" + generatedId,
schedule_id: scheduleId,
attendance: data.map((student) => ({
attendance_id: student.nisn + generatedId,
student_id: student.nisn,
status: "Hadir",
description: ""
})),
});
console.log(values);
} catch (error) {
console.log(error);
}
};
return (
<div className="flex flex-col h-full gap-6 overflow-y-hidden flex-nowrap whitespace-nowrap">
<h1 className="sm:text-3xl text-2xl font-bold leading-none text-neutral-900">
Presensi
</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<div className="flex flex-col justify-between gap-8 py-4 h-full overflow-y-auto">
{data
.map((student, index) => (
<div key={student.nisn}>
<FormField
control={form.control}
name={`attendance.${index}.student_id`}
render={({ field }) => (
<FormItem className="grid w-full max-w-sm items-center gap-1.5">
<FormControl>
<Input
{...field}
className="border-0"
disabled
/>
</FormControl>
<FormMessage/>
</FormItem>
)}
/>
<FormField
control={form.control}
name={`attendance.${index}.status`}
render={({ field }) => (
<FormItem className="">
<Popover>
<PopoverTrigger>
<FormControl>
<Badge className="w-[100px] flex justify-center">
{field.value ? field.value : "Select Status"}
</Badge>
</FormControl>
<FormMessage/>
</PopoverTrigger>
<PopoverContent className="overflow-hidden p-0">
<ul className="text-center">
{statuses.map((status) => (
<li
key={status}
className="py-0.5 px-2 border-b"
onClick={() => {
form.setValue(
`attendance.${index}.status`,
status
);
}}
>
{status}
</li>
))}
</ul>
</PopoverContent>
</Popover>
</FormItem>
)}
/>
</div>
))}
<div className="flex justify-end gap-4">
<Button type="submit">Done</Button>
</div>
</div>
</form>
</Form>
</div>
);
};
export default Presensi;
Schema :
import { z } from "zod";
export const AttendanceSchema = z.object({
attendance_list_id: z.string().min(1, { message: "List ID is required!" }),
attendance: z.array(
z.object({
attendance_id: z.string().min(1, { message: "ID is required!" }),
student_id: z.string().min(1, { message: "Student is required!" }),
status: z.string().min(1, { message: "status is required!" }),
description: z.optional(z.string().max(225, { message: "Maximum 255 characters!" })),
})
)
});
i try to put error message on the form think maybe its the problem on the validation but even the error message wont show up.
2
Answers
You will get formState from that and in will give you errors ( formState: { errors }) object. try to console it may there some error in validation so you will get validation error in errors object.
change this line:
to this:
this way you can see form errors if you have any.