0

Hello fellow developers.

I'm developing a masked birthday input in vuejs that need to check that the date is now minus 18 years, to check if my users can buy alcohol.

It's working great, but i'm struggling with it when the birthday is passed as a default value into my input, eq. it won't let me update it...

I'm using VeeValidate (VeeValidate) for the validation process, CleaveJs (CleaveJS) for the masking and Date-fns (Date-fns) for the dating utility.

This is my code :

In my form

<vv-form-mask-input
 id="birthday"
 label="birthday"
 name="birthday"
 v-model="birthday"
 required
 placeholder="JJ/MM/AAAA"
 :cleave="{date: true, datePattern: ['d', 'm', 'Y'] }"
 :validate="'legalAge|date_format:dd/MM/yyyy'"
 :val="this.user.birthday"
/>

My VvFormMaskInput

<template>
  <div class="field-container">
    <label v-if="type != 'hidden'" :for="id" class="form-label">{{ $t(`forms.${label}`) }} {{ showAsterisk }}</label>

    <div class="row">
      <input
        v-cypress="testId"
        :type="type"
        :disabled="disabled"
        :id="id"
        class="form-input"
        v-validate="validate !== '' ? validate : false"
        :value="val"
        :ref="id"
        :name="id"
        @input="$emit('input', $event.target.value)"
        v-cleave="cleave"
        :placeholder="placeholder"
        mode="lazy"
      />

      <div class="valid-field">
        <img v-if="isValid" src="@/assets/input-valid-check-mark.png" />
      </div>
    </div>
    <!-- Helper -->
    <span v-if="this.label == 'birthday'" class="form-error birthday">{{ $t(`forms.helps.${label}`) }}</span>
    <!-- Error messages -->
    <span class="form-error">{{ errors.first(id) }}</span>
  </div>
</template>

<script>

export default {
  name: 'VvFormMaskInput',
  computed: {
    showAsterisk() {
      if ((this.validate && this.validate.indexOf('required') !== -1) || this.label == 'birthday') {
        return '*'
      }

      return ''
    }
  },
  data: () => ({
    isValid: false
  }),
  props: {
    id: {
      type: String
    },
    label: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: 'text'
    },
    val: {
      type: String,
      default: ''
    },
    validate: {
      type: String,
      default: null
    },
    disabled: {
      type: Boolean,
      default: false
    },
    testId: {
      type: String,
      default: null
    },
    cleave: {
      type: Object,
      default: null
    },
    placeholder: {
      type: String,
      default: ''
    }
  },
  inject: ['$validator'],
  watch: {
    value: async function(val) {
      if (this.validate === '') {
        this.isValid = val !== ''
      } else {
        this.isValid = (await this.$validator.verify(val, this.validate)).valid
      }
    }
  }
}
</script>

My legalAge custom rule for VeeValidate

import parse from 'date-fns/parse'
import format from 'date-fns/format'
import subYears from 'date-fns/subYears'

/**
 * Rule for legal age > 18 years old
 * @argument {value} Date
 */ 
export const legalAge = (value) => {
  let d1 = new Date(parse(value, 'dd/MM/yyyy', new Date()))
  let d2 = new Date(parse(format(subYears(new Date(), 18), 'dd/MM/yyyy'), 'dd/MM/yyyy', new Date()))
  return d1 <= d2
};

When I load my form, and there is not previous birthday, I've go my input with a placeholder "JJ/MM/YYYY". I can enter a valid date in the format "dd/MM/yyyy" and valid my form. It also display me when it's a date for a legal age (above 18 years old) or no.

When I load this same form, but I've got a birthday already set, my input receive this as default value, so that's ok, but I can't change this input value...

If you have ever used VeeValidate and CleaveJS for this type of input, I would love to hear if you faced the same type of issue.

Thank you for your help !

Bloodbee
  • 827
  • 8
  • 23

0 Answers0