Redwood Password Component

Dear RW community,

I am currently implementing password validation in the front-end and utilizing a logic that returns an error if any of the conditions are not met. While this approach functions correctly and presents no issues, I am seeking an approach that allows for the simultaneous display of all errors as the user types their password. This would provide a more user-friendly experience, as it would allow for a live update of the password’s validity as the user enters it. Additionally, I would like to enhance the user experience by visually indicating when each condition for the password is satisfied, for example, by turning the condition green.
Thanks in advance.

<PasswordField
  name="password"
  className="rw-input"
  errorClassName="rw-input rw-input-error"
  autoComplete="current-password"
  validation={{
    validate: (value) => {
      if (value.length < 8) {
        return 'Password must be at least 8 characters'
      } else if (!value.match(/[A-Z]/)) {
        return 'Password must contain at least one uppercase letter'
      } else if (!value.match(/[a-z]/)) {
        return 'Password must contain at least one lowercase letter'
      } else if (!value.match(/[0-9]/)) {
        return 'Password must contain at least one number'
      } else if (!value.match(/[!@#$%^&*()]/)) {
        return 'Password must contain at least one special character'
      } else {
        return true
      }
    },
    required: {
      value: true,
      message: 'Password is required',
    },
  }}
/>

Here is how I did it in case someone else is looking at a similar solution.
First define a variable like:

const checkErrors = (password) => {
    const length = password.length >= 8
    const uppercase = /[A-Z]/.test(password)
    const lowercase = /[a-z]/.test(password)
    const number = /[0-9]/.test(password)
    const special = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)
    const whitespace = !/\s/.test(password)

    setErrors({
      length: length,
      uppercase: uppercase,
      lowercase: lowercase,
      number: number,
      special: special,
      whitespace: whitespace,
    })
  }
  const errMsg = (error) => {
    if (error === 'length') {
      return 'Password must be at least 8 characters'
    } else if (error === 'uppercase') {
      return 'Password must contain at least one uppercase letter'
    } else if (error === 'lowercase') {
      return 'Password must contain at least one lowercase letter'
    } else if (error === 'number') {
      return 'Password must contain at least one number'
    } else if (error === 'special') {
      return 'Password must contain at least one special character'
    } else if (error === 'whitespace') {
      return 'Password must not contain any whitespace'
    }
  }

Then you password field should look like:

<PasswordField
  name="password"
  className="rw-input"
  errorClassName="rw-input rw-input-error"
  autoComplete="new-password"
  validation={{
    validate: (password) => {
      checkErrors(password)
    },
    required: {
      value: true,
      message: 'Password is required',
    },
  }}
/>
{/* <FieldError name="password" className="rw-field-verified" /> */}
{/* <FieldError name="password" className="rw-field-error" /> */}
{Object.keys(errors).map((error, index) => {
  let color = errors[error] ? 'green' : 'red'
  return (
    <div key={index}>
      <div
        className={
          color == 'red'
            ? 'rw-field-error'
            : 'rw-field-verified'
        }
      >
        {color === 'green' ? (
          <DoneIcon style={{ color: color }} />
        ) : (
          <CloseIcon style={{ color: color }} />
        )}
        {errMsg(error)}
      </div>
    </div>
  )
})}

I hope this helps.

1 Like