'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>
What am I doing wrong that the regex is not working as expected?
Solution 1:[1]
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>
Solution 2:[2]
I had problems making this work with complex regex using the built in v-validate rule. I have a regex that checks to see if a password field contains BOTH a letter AND a number. The regex for this is : /^(?=.[0-9])(?=.[a-zA-Z])([a-zA-Z0-9]+)$/g
I spent ages trying to make this work with the built in regex: parameter and had no success, so in the end I wrote my own extender. So in my mounted:
this.$validator.extend('complex_password', {
validate(value, args) {
return Util.isComplexPassword(value);
}
})
and then added a function to my utils lib:
isComplexPassword(value) {
tester = /^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$/g
isMatch = !tester.test(String(value))
return !isMatch
},
then finally, hooked it into my field validation:
v-validate="'required|min:8|complex_password'"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |