Tech: ReactJS and TailwindCSS. Currently, the email field is validated and error is shown as the user types. Code:
<div className='flex w-full flex-col space-y-2'>
<label htmlFor='email' className='text-sm text-gray-600'>
Email address
</label>
<input
type='email'
id='email'
autoComplete='email'
required
className='peer relative block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 invalid:text-pink-600 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 focus:invalid:border-pink-500 focus:invalid:ring-pink-500 sm:text-sm'
value={email}
onChange={e => setEmail(e.target.value)}
/>
<p className={`invisible mt-2 text-sm text-pink-600 ${email.length > 0 ? 'peer-invalid:visible' : ''}`}>
Please provide a valid email address.
</p>
</div>
Can I show it at tab pressing or when switching to a new field instead? I tried using onBlur / onFocus at
<p className={`invisible mt-2 text-sm text-pink-600 ${onBlur ? 'peer-invalid:visible' : ''}`}>
But this didn't seem to work. How to do it?
CodePudding user response:
You need to attach an onBlur
handler to the input, and use that to manipulate a state item which will indicate if the field has been "touched" or not. The way you used onBlur
dosn't make sense as onBlur
is a prop of input
and its a function, not a bool. You have to do the heavy lifting to get the bool that says "did they touch this field".
const [showEmailError, setShowEmailError] = useState(false)
// ...
<div className='flex w-full flex-col space-y-2'>
<label htmlFor='email' className='text-sm text-gray-600'>
Email address
</label>
<input
type='email'
id='email'
autoComplete='email'
required
className='peer relative block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 invalid:text-pink-600 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 focus:invalid:border-pink-500 focus:invalid:ring-pink-500 sm:text-sm'
value={email}
onChange={e => {
setEmail(e.target.value)
setShowEmailError(false)
}}
onBlur={e => setShowEmailError(true)}
/>
<p className={`invisible mt-2 text-sm text-pink-600 ${email.length > 0 && showEmailError ? 'peer-invalid:visible' : ''}`}>
Please provide a valid email address.
</p>
</div>
Note that writing form logic like this can be very tiresome with lots of fields. I'd highly recommend you look into a popular form lib https://react-hook-form.com/ which covers all the edge cases and and already provides the behaviour you are looking for.