Reputation: 1
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:
onChange = (e) => console.log(e.target.value)
to check whether any input is detected and React Hook Form's onChange function does detect and log the value correctly.I expect the value that is typed into the input to be registered correctly with React Hook Form.
Upvotes: 0
Views: 164