2

suppose we have a password field and we want to do some validations of length, specialcharacters, numbers, upper case and lower case etc, only if the field has a value

how can we do that with vuelidate.

here I am import vuelidate

import { required, minLength, maxLength, email, sameAs } from 'vuelidate/lib/validators'

Here the validations

validations: {
    editedItem: {
      firstname: { required, minLength: minLength(3), maxLength: maxLength(20) },
      lastname: { required, minLength: minLength(3), maxLength: maxLength(20) },
      email: { required, email },
      password: {
        required,
        minLength: minLength(6),
        maxLength: maxLength(15),
        oneNumber,
        oneUpperCase,
        oneLowerCase,
      },
      repassword: {
        sameAsPassword: sameAs('password'),
      },
    },
  }

,

oneNumber, oneUpperCase and oneLowerCase are custom validations:

const oneNumber = (value) => /[0-9]/.test(value)
const oneUpperCase = (value) => /[A-Z]/.test(value)
const oneLowerCase = (value) => /[a-z]/.test(value)

I will forever appreciate any help or advice

4
  • I usually use their isDirty, but it is not exactly what you want because it will show invalid value when user clears the password field. Commented Jun 12, 2020 at 3:19
  • Exactly, i am thinking of a custom validator, i will try and let you know. Thanks a lot Commented Jun 12, 2020 at 3:41
  • Did you find a solution to this? I'm facing a similar issue. Commented Jul 17, 2020 at 14:21
  • Not yet @Brent, i worked in another things but i hope next week find a solution Commented Jul 17, 2020 at 19:30

1 Answer 1

5

My solution involves a separate "custom validators" file.

validators.js:

import { helpers as vuelidateHelpers } from 'vuelidate/lib/validators'

export const oneUppercase = value => {
  if (!vuelidateHelpers.req(value)) {
    return true
  }
  const match = value.match(/[A-Z]/g) || []
  return match.length >= 1
}
export const oneLowercase = value => {
  if (!vuelidateHelpers.req(value)) {
    return true
  }
  const match = value.match(/[a-z]/g) || []
  return match.length >= 1
}
export const oneSpecial = value => {
  if (!vuelidateHelpers.req(value)) {
    return true
  }
  const match = value.match(/[ !@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/g) || []
  return match.length >= 1
}
export const oneNumber = value => {
  if (!vuelidateHelpers.req(value)) {
    return true
  }
  const match = value.match(/\d/g) || []
  return match.length >= 1
}

In the component, with visual formatting to let the user know if their password meets the requirement:

<template>
  <form>
    <label for="password">Password</label>
    <input
            id="password"
            name="password"
            type="password"
            v-model="form.password"
            @blur="$v.form.password.$touch()"
            @input="validatePassword"
    />
    <label for="confirmPassword">Confirm Password</label>
    <input
            id="confirmPassword"
            name="confirmPassword"
            type="password"
            v-model="form.confirmPassword"
            @blur="$v.form.confirmPassword.$touch()"
    />
    <ul>
      <li>
          {{
          passwordValidations.eightCharacters ?
          '✓':
          '╳'
          }}
        <span class="ml-1">MUST contain 8 characters</span>
      </li>
      <li>
          {{
          passwordValidations.oneUppercase ?
          '✓':
          '╳'
          }}
        <span class="ml-1">MUST contain one uppercase letter</span>
      </li>
      <li>
          {{
          passwordValidations.oneLowercase ?
          '✓':
          '╳'
          }}
        <span class="ml-1">MUST contain one lowercase letter</span>
      </li>
      <li>
          {{
          passwordValidations.oneNumber ?
          '✓':
          '╳'
          }}
        <span class="ml-1">MUST contain one number</span>
      </li>
      <li>
          {{
          passwordValidations.oneSpecial ?
          '✓':
          '╳'
          }}
        <span class="ml-1">MUST contain one special character</span>
      </li>
    </ul>
  </form>
</template>

<script>
  import {
    required,
    minLength,
    sameAs,
  } from 'vuelidate/lib/validators'
  import {
    oneNumber,
    oneSpecial,
    oneUppercase,
    oneLowercase,
  } from '../validators'

  export default {
    data () {
      return {
        form: {
          password: '',
          confirmPassword: '',
        },
        passwordValidations: {
          eightCharacters: false,
          oneUppercase: false,
          oneLowercase: false,
          oneNumber: false,
          oneSpecial: false,
        },
      }
    },
    computed: {
      passwordErrors () {
        const errors = []
        if (!this.$v.form.password.$dirty) return errors
        !this.$v.form.password.required && errors.push('Password is required.')
        return errors
      },
      confirmPasswordErrors () {
        const errors = []
        if (!this.$v.form.confirmPassword.$dirty) return errors
        !this.$v.form.confirmPassword.required && errors.push('Please confirm your password.')
        !this.$v.form.confirmPassword.sameAsPassword && errors.push('Passwords don\'t match')
        return errors
      },
    },
    methods: {
      validatePassword () {
        this.passwordValidations.eightCharacters = this.$v.form.password.eightCharacters
        this.passwordValidations.oneUppercase = this.$v.form.password.oneUppercase
        this.passwordValidations.oneLowercase = this.$v.form.password.oneLowercase
        this.passwordValidations.oneNumber = this.$v.form.password.oneNumber
        this.passwordValidations.oneSpecial = this.$v.form.password.oneSpecial
      },
    },
    validations: {
      form: {
        password: {
          required,
          minLength: minLength(8),
          oneUppercase,
          oneSpecial,
          oneNumber,
          oneLowercase,
        },
        confirmPassword: {
          required,
          sameAsPassword: sameAs('password'),
        },
      },
    },
  }
</script>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.