aquaVoyager
aquaVoyager

Reputation: 1

FIXED React Hook Form input's value doesn't register with DaisyUI

Edit 20.09.2024: Naming the form dynamically with the task's specific ID fixed my issue, now RHF can read and validate the value that is typed in the input, demonstrated below in the ...register part:

<input
  placeholder={label}
  type="text"
  {...register(
    `taskLabel-${currentTask.id}`, // <--- naming the form explicitly fixed my problem
    {
      required: "Please enter a label!",
      minLength: {
        value: 3,
        message:
          "Label must be at least 3 characters long!",
      },
      maxLength: {
        value: 15,
        message:
          "Label must be less than 15 characters long!",
      },
    },
  )}/>

Edit 12.8.2024: I have used RHF's dev tools, it seems any value within the form doesn't register to React Hook Form despite the value appearing with RHF's onChange function. I will also update the code block to include the part that includes DaisyUI, which I forgot to do in the beginning. The "touched" attribute also turns to true when typing into the input, but the value stays empty.

I'm using DaisyUI, React and React Hook Form, there is a button that displays a form to edit a task's title when clicked. There is a minLength rule of 5 characters and an input is required to submit the form. The form validation works fine when I try it in another component on another page but when I try it in a dialog modal from DaisyUI, I'm getting an error with the "required" type in console. Here are the errors that I found that could be relevant to the issue:

taskTitle: Object { type: "required", message: "This field is required!", ref: input.grow }
  message: "This field is required!"
  ref: <input class="grow" type="text" placeholder="Fix Arch Linux" name="taskTitle">
    "__reactEvents$7sb6xdad22s": Set [ "invalid__bubble" ]
_reactName: "onSubmit"
​
_targetInst: null
​
bubbles: true
​
cancelable: true
​
currentTarget: null
​
defaultPrevented: true
​
eventPhase: 3
​
isDefaultPrevented: function functionThatReturnsTrue()​
isPropagationStopped: function functionThatReturnsFalse()
​
isTrusted: true
​
nativeEvent: submit { target: form, isTrusted: true, submitter: button.text-3xl.text-primary.shadow
, … }
​
target: <form>
​
timeStamp: 4223735
​
type: "submit"

Below is the specific code block containing the form with the hooks above, this part is nested in the modal-box part of DaisyUI's modal, specifically in a div like so: <div className="modal-box w-screen overflow-visible">

Code block containing the form, nested in the div I specified above with the rest of the page containing the tasks:

function Tasks() {
const [taskTitleEdit, setTaskTitleEdit] = useState(false);

const { register, handleSubmit, reset } = useForm();

function onSubmitTitle(data) {
  console.log("SUCCESS:", data);
  toast.success("Edited task title!");
  setTaskTitleEdit(false);
  reset();
}
function onErrorTitle(error) {
  toast.error("Error, check developer console!");
  console.log("FAILED!:", error);
  reset();
}

return (
<div className="flex flex-col">
                {/* Task modal */}
                <div>
                  <button
                    className="cursor-pointer text-base"
                    onClick={() =>
                      document.getElementById(`my_modal_${index}`).showModal()
                    }
                  >
                    {currentTask.task_title}
                  </button>
                  {/* -----MODAL BEGINNING----- */}
                  <dialog
                    id={`my_modal_${index}`}
                    className="modal modal-bottom sm:modal-middle"
                  >
                    <div className="modal-box w-screen overflow-visible">
                      <div className="mb-2 flex items-center gap-2">
                        {/* TASK CHECKBOX */}
                        <input
                          type="checkbox"
                          checked={currentTask.task_status}
                          onChange={onChangeFunc}
                          className="checkbox-primary checkbox checkbox-sm"
                        />
                        {!taskTitleEdit ? (
                          /* TASK TITLE */
                          <OptionsButton
                            tabIndex={index}
                            dropStyle={SELECT_STYLE}
                            options={taskTitleOperation}
                            style={"text-lg font-bold cursor-pointer"}
                            taskData={currentTask}
                          >
                            {currentTask.task_title}
                          </OptionsButton>
                        ) : (
                          // Task title edit form
                          <>
                            <form
                              onSubmit={handleSubmit(
                                onSubmitTitle,
                                onErrorTitle,
                              )}
                            >
                              <label className="input input-bordered input-primary flex items-center gap-2">
                                <input
                                  type="text"
                                  className="grow"
                                  placeholder={currentTask.task_title}
                                  {...register("taskTitle", {
                                    required: "This field is required!",
                                  })}
                                />
                                <button
                                  type="submit"
                                  className="text-3xl text-primary shadow"
                                >
                                  <CiSquareCheck />
                                </button>
                                <button
                                  type="button"
                                  className="text-3xl text-primary shadow"
                                  onClick={() => handleEditTitle(currentTask)}
                                >
                                  <CiSquareRemove />
                                </button>
                              </label>
                              {errors.taskTitle?.type && (
                                <span>{errors.taskTitle?.message}</span>
                              )}
                            </form>
                            <DevTool control={control} />
                          </>
                        )}
                      </div>
                      {/* TASK DESCRIPTION */}
                      {currentTask.task_description ? (
                        <p className="max-h-64 overflow-scroll">
                          {/* Description limit is 500 characters */}
                          {currentTask.task_description}
                        </p>
                      ) : (
                        <div>
                          <CiTextAlignLeft
                            fontSize={"1.2rem"}
                            className="mr-1 inline"
                          />
                          <span className="italic text-base-content/75">
                            No description
                          </span>
                        </div>
                      )}
                      <div className="divider m-1" />
                      <div className="flex flex-col gap-2">
                        {/* TASK DUE DATE */}
                        <div className="flex items-center gap-2">
                          <CiCalendarDate className="text-2xl text-primary" />
                          {/* Will filter by date on click */}
                          <DatePicker
                            dateFormat="dd/MM/yyyy"
                            todayButton="Today"
                            selected={currentTask.task_due}
                            onChange={(date) => setStartDate(date)}
                            customInput={<CustomInput />}
                            calendarClassName="border border-primary"
                            popperClassName="ml-12"
                          />
                        </div>
                        {/* TASK LABEL */}
                        <div className="flex items-center gap-2">
                          <CiShoppingTag className="flex-none text-2xl text-primary" />
                          {/* Will filter by label on click */}
                          <div>
                            <div className="flex flex-wrap gap-1 pr-2">
                              {currentTask?.task_labels.map((label, index) => (
                                <OptionsButton
                                  tabIndex={index}
                                  key={index}
                                  style={
                                    "cursor-pointer border border-primary p-1 rounded"
                                  }
                                  dropStyle={SELECT_STYLE}
                                  options={taskLabelOperation}
                                  taskData={currentTask}
                                >
                                  {label}
                                </OptionsButton>
                              ))}
                            </div>
                          </div>
                        </div>
                        {/* TASK PRIORITY */}
                        <div className="flex items-center gap-2">
                          <CiFlag1 className="text-2xl text-primary" />
                          {/* Will filter by priority on click */}
                          <OptionsButton
                            tabIndex={index}
                            dropStyle={"flex text-base gap-2 p-2"}
                            style={"cursor-pointer"}
                            options={editTaskPriority}
                            taskData={currentTask}
                          >
                            Priority {currentTask.task_priority}
                          </OptionsButton>
                        </div>
                      </div>
                      <div className="modal-action">
                        <form method="dialog" className="flex gap-2">
                          {/* if there is a button in form, it will close the modal */}
                          <button className="btn btn-primary">
                            Mark as done
                          </button>
                          <button
                            className="btn btn-outline btn-primary"
                            onClick={() => setTaskTitleEdit(false)}
                          >
                            Close
                          </button>
                        </form>
                      </div>
                    </div>
                  </dialog>
                  {/* -----MODAL END----- */}
                </div>
                {currentTask.task_description && (
                  <p className="line-clamp-3">{currentTask.task_description}</p>
                )}
                <div className="flex gap-2">
                  <div
                    className={`badge badge-outline badge-sm mt-1 ${
                      currentTask.task_priority === 1
                        ? "text-priority-1"
                        : currentTask.task_priority === 2
                          ? "text-priority-2"
                          : currentTask.task_priority === 3
                            ? "text-priority-3"
                            : currentTask.task_priority === 4
                              ? "text-priority-4"
                              : ""
                    }`}
                  >
                    P{currentTask.task_priority}
                  </div>
                  <div className="badge badge-accent badge-outline badge-sm mt-1">
                    {dateFormatter(currentTask.task_due)}
                  </div>
                </div>
              </div>
)

So far I've tried:

I expect the value that is typed into the input to be registered correctly with React Hook Form.

Upvotes: 0

Views: 164

Answers (0)

Related Questions