following the replies below I now have the following
import { useState } from "react";
import Head from "next/head";
import Link from "next/link";
import Image from "next/image";
import Background from "../../../../public/images/option1.png";
import Router from "next/router";
import { signIn } from "next-auth/client";
import { useForm } from "react-hook-form";
import { ErrorMessage } from "@hookform/error-message";
import { SaveIcon } from "@heroicons/react/outline";
export default function Confirm() {
const {
register,
formState: { errors },
handleSubmit,
} = useForm({
criteriaMode: "all",
});
const [old_password, setOldPassword] = useState("");
const [password, setPassword] = useState("");
const [confirm_password, setConfirmPassword] = useState("");
const onSubmit = async () => {
const status = await signIn("credentials", {
redirect: false,
email: email,
});
Router.push("/dashboard");
};
return (
<>
<Head>
<title>Ellis Development - Confirm Password</title>
</Head>
<div className="relative">
<div className="md:flex">
{/* Image */}
<div className="flex items-center justify-center bg-blue-700 h-screen lg:w-96">
<Image src={Background} width={350} height={350} layout="fixed" />
</div>
{/* Contact form */}
<div className="flex flex-col justify-center py-10 px-6 sm:px-10 w-full">
<h1 className="text-4xl font-extrabold text-grey-800">
Reset your password
</h1>
{/* errors */}
<ErrorMessage
errors={errors}
name="formErrors"
render={({ messages }) =>
messages && (
<div className="mt-6 border-2 border-red-600">
<div className="bg-red-600 text-white py-2 px-4">
<h6>Following errors have occurred</h6>
</div>
<div className="text-grey-800 py-2 px-4">
<div className="flex flex-col gap-2">
{Object.entries(messages).map(([type, message]) => (
<div
className="flex flex-col gap-y-6 sm:gap-x-8"
key={type}
>
<small className="text-red-500">{message}</small>
</div>
))}
</div>
</div>
</div>
)
}
/>
<form
onSubmit={handleSubmit(onSubmit)}
className="mt-6 flex flex-col gap-y-6 sm:gap-x-8"
>
{/* old_password field */}
<div>
<label
htmlFor="old_password"
className="block text-sm font-medium text-gray-900"
>
Old Password
</label>
<div className="mt-1">
<input
{...register("formErrors", {
required: "Old password is required",
})}
type="password"
name="old_password"
id="old_password"
className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
onChange={(event) => setOldPassword(event.target.value)}
/>
</div>
</div>
{/* password field */}
<div>
<label
htmlFor="password"
className="block text-sm font-medium text-gray-900"
>
Password
</label>
<div className="mt-1">
<input
{...register("formErrors", {
required: "Password is required",
})}
type="password"
name="password"
id="password"
className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
onChange={(event) => setPassword(event.target.value)}
/>
</div>
</div>
{/* confirm_password field */}
<div>
<label
htmlFor="confirm_password"
className="block text-sm font-medium text-gray-900"
>
Confirm Password
</label>
<div className="mt-1">
<input
{...register("formErrors", {
required: "Confirm password is required",
})}
type="password"
name="confirm_password"
id="confirm_password"
className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
onChange={(event) => setConfirmPassword(event.target.value)}
/>
</div>
</div>
<div className="flex items-center justify-between sm:col-span-2">
<div>
<button
type="submit"
className="mt-2 mr-2 w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-blue-700 hover:bg-blue-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 sm:w-auto"
>
<SaveIcon className="w-4 h-4 mr-4" />
Submit
</button>
</div>
<div>
<Link href="/dashboard/auth/login">
<a className="underline decoration-blue-500 decoration-4 hover:decoration-2 mr-4">
Login
</a>
</Link>
</div>
</div>
</form>
</div>
</div>
</div>
</>
);
}
However, only one of the errors is showing,
There are multiple input fields and I have took a look at the docs, not sure what I'm doing wrong though.
original question I'm currently using the react-hook-form library, I have all of the errors above the form like so
{/* errors */}
{errors.length > 0 && (
<div className="mt-6 border-2 border-red-600">
<div className="bg-red-600 text-white py-2 px-4">
<h4>{errors.length} errors occurred:</h4>
</div>
<div className="text-grey-800 py-2 px-4">
<div className="flex flex-col gap-2">
{/* old_password errror */}
<div className="flex flex-col gap-y-6 sm:gap-x-8">
{errors.old_password && (
<small className="text-red-500">
• Old password is required
</small>
)}
</div>
{/* password error */}
<div className="flex flex-col gap-y-6 sm:gap-x-8">
{errors.password && (
<small className="text-red-500">
• Password is required
</small>
)}
</div>
{/* confirm_password errror */}
<div className="flex flex-col gap-y-6 sm:gap-x-8">
{errors.confirm_password && (
<small className="text-red-500">
• Confirm password is required
</small>
)}
</div>
</div>
</div>
</div>
)}
This works and the errors show, not sure if there's a way to map the errors to make the code more clear so any ideas there would be great.
However, how to I go about hiding the errors block, I have {errors.length > 0 && (
, however this doesn't seem to work.
Any help would be great.
CodePudding user response:
Since errors
is a object .length
won't work for it. But you can use Object.keys(errors).length > 0
to dynamic display the error block. Something like that:
{Object.keys(errors).length > 0 && (
<div className="mt-6 border-2 border-red-600">
<div className="bg-red-600 text-white py-2 px-4">
<h6>Following errors have occurred</h6>
</div>
<div className="text-grey-800 py-2 px-4">
<div className="flex flex-col gap-2">
{/* Here you put one ErrorMessage for each input*/}
<ErrorMessage
errors={errors}
name="old_password"
render={({ message }) => (
<div className="flex flex-col gap-y-6 sm:gap-x-8" key={type}>
<small className="text-red-500">{message}</small>
</div>
)}
/>
</div>
</div>
</div>
You input must be like this:
<input
{...register("old_password", { required: "Old password is required" })}
id="old_password"
type="password"
className="your classes"
onChange={(event) => setOldPassword(event.target.value)}
/>