Home > Back-end >  Validate fields and show the error (if any) at tab pressing or when switching to a new field instead
Validate fields and show the error (if any) at tab pressing or when switching to a new field instead

Time:10-11

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>

emailFieldValidation

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.

  • Related