skip to Main Content

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


  1. const form = useForm({
       resolver: zodResolver(AttendanceSchema),
       defaultValues: {
         attendance_list_id: "123",
         attendance: [
           {
             attendance_id: "123",
             status: "Hadir",
             student_id: "123",
             description: "",
           },
         ],
       },
     });
    
    console.log(form);// Console this item, 
    

    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.

    Login or Signup to reply.
  2. change this line:

    <form onSubmit={form.handleSubmit(onSubmit)}>
    

    to this:

    <form onSubmit={form.handleSubmit(onSubmit, (errors) => console.log(errors)}>
    

    this way you can see form errors if you have any.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search