Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vee-validate regex not working

I need to validate US phone number XXX-XXX-XXXX using vee-validate with this basic regex: (?:\d{3}-)\d{3}-\d{4}. The regex works fine by itself, but does not work with vee-validate, and I'm unsure why.

Markup

<!DOCTYPE html>
<html>
   <head>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/vee-validate@latest/dist/vee-validate.js"></script>
   </head>
   <body>
      <div id="app">
         <form action='#' method='POST'>

            <input v-validate="'required|regex:^(?:\(\d{3}\)|\d{3}-)\d{3}-\d{4}$'" :class="{'input': true, 'is-danger': errors.has('phone_primary') }" class="input is-info" type="text" name='phone_primary' value="$phone_primary" placeholder="404-555-1212" size="15">
            <span v-show="errors.has('phone_primary')" class="help is-danger">{{ errors.first('phone_primary') }}</span>

            <button class="button is-link" name='submitform' value='go'>Submit</button>
         </form>
      </div>
      <script>
         Vue.use(VeeValidate);
         new Vue({
           el: '#app',
           template: '#app',
           data: {
              phone_primary: null
           }
         });
      </script>

    </body>
</html>

Fiddle

What am I doing wrong that the regex is not working as expected?

like image 539
a coder Avatar asked Dec 24 '22 06:12

a coder


1 Answers

The v-validate directive accepts a string value which is a list of validations separated by a pipe (|). Since the pipe is also used inside the regex pattern (as an alternation operator) the string command gets invalidated. As a work-around, pass an object rather than a string value.

Besides, the regex in vee-validate requires regex delimiters, / chars around the pattern.

So, you may use

v-validate="{ required: true, regex:/^(?:\(\d{3}\)|\d{3}-)\d{3}-\d{4}$/ }"

See the updated fiddle.

Note the regex does not match an empty string, so empty input won't be valid.

Also, if you use it in some component that does not allow passing an object, use a custom rule:

Vue.use(VeeValidate);

new Vue({
  el: '#app',
  created() {
    this.$validator.extend('phone_pattern', {
      getMessage(field, val) {
        return 'The ' + field + ' field should match the "(XXX)XXX-XXX-XXXX" or "123-XXX-XXXX" pattern!'
      },
      validate(value, field) {
        return /^(?:\(\d{3}\)|\d{3}-)\d{3}-\d{4}$/.test(value);
      }
    })
  },
  methods: {
    validate() {
      this.$validator.validateAll()
        .then((result) => {
          if (result) {
            alert('valid!');
          }
        });
    }
  }
});
.text-danger {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vee-validate/2.0.9/vee-validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <form action="" @submit.prevent="validate">
    <div class="form-group">
      <label for="">Phone number:</label>
      <input name="phone" type="text" class="form-control" v-validate="'required|phone_pattern'" />
      <span class="text-danger">{{ errors.first('phone') }}</span>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
</div>
like image 82
Wiktor Stribiżew Avatar answered Jan 06 '23 07:01

Wiktor Stribiżew