vee-validate not working with bootstrap-vue - vuejs2

I'm trying to use vee-validate for form validation with bootstrap-vue, and cannot get anything to work. Basically, I want to do:
<b-form-input v-model="emailText"
placeholder="Enter email"
v-validate="'required|email'"
name="email"
type="text">
<b-row>
<span>{{ errors.first('email') }}</span>
</b-row>
</b-form-input>
But I don't see anything when I type a non-email address in the field. However, if I change:
b-form-input to input
then everything works. Is there a workaround for this behavior? Any help would be greatly appreciated.

You have put the error messages inside the <b-form-input>, which has no internal slot, so the error messages aren't rendered. If you move them to after the input, it should fix your issue:
<b-form-input v-model="emailText"
placeholder="Enter email"
v-validate="'required|email'"
name="email"
type="text">
</b-form-input>
<b-row>
<span>{{ errors.first('email') }}</span>
</b-row>
You can also use Bootstrap-Vue's state and invalid-feedback properties on the <b-form-input> and a surrounding <b-form-group> to display validation errors with a better accessibility. All of this is demonstrated in this codepen

Related

How to hide el-form-item__error after field valid?

vue 3.2.31
vee-validate 4.5.10
element-plus 2.1.6
On input event, it shows validation error message properly. But on blur event, it shows is required error message. Also on blur event, even if validation succeeded, it shows is required error message. But when form valid, meta.valid is true and vice versa.
On that time console like follows:
My code:
<VeeForm v-slot="{ isSubmitting, meta }" #submit="submitForm" ref="loginFormObserver" as="div">
<el-form :model="loginForm" ref="loginForm" name="loginForm" size="small" label-position="left" label-width="30%">
<VeeField :rules="'required|email'" name="Username" v-slot="{ field, errorMessage }">
<el-form-item :error="errorMessage" label="Username" required>
<el-input v-model="loginForm.username" type="email" clearable status-icon v-bind="field">
</el-input>
</el-form-item>
</VeeField>
<el-form-item class="text-center">
<el-button class="login-btn" native-type="submit" type="primary" :disabled="!meta.valid || isSubmitting">{{ trans('common.login') }} </el-button>
</el-form-item>
</el-form>
</VeeForm>
If I avoid required attribute fromel-form-item, it works properly. But it removes red asterisk (star) beside labels of required fields.
This might be element-plus validation causing the confusion. You can disable their validation with: :validate-event="false". Which should give you the asterisk and remove the validation behavior from element-plus.
<el-input v-model="loginForm.username" type="email" clearable status-icon v-bind="field" :validate-event="false"></el-input>

How to show vee-validate errors in custom tooltips?

In vuejs 2 app using vee-validate ^3.4.14 I have several inputs on modal form of fixed height.
On validation errors I got validation error messages below of inputs, as I have layout like :
<div class="form-group">
<ValidationProvider
name="password_confirmation"
rules="required"
v-slot="{ errors }"
>
<div class="input-group">
<input type="password"
v-model="password_confirmation"
id="password_confirmation"
name="password_confirmation"
class="form-control editable_field"
placeholder="Password confirmation"
autocomplete=off
ref="password"
>
</div>
<p class="error">{{ errors[0] }}</p>
</ValidationProvider>
</div>
But these messages break layout of modal form, as height of modal form is increased and elements
on bottom of the form are hidden. If there is a way to show these errors in some other way ?
Say a) select input with “error_border” class and b) show some tooltip message near with any input with error text?
Thanks in advance!

Vue.js2 v-for separate protperties

With the code below, if I press the "Edit" button, I change the disabled state all the rows, how can I separate this? I mean, once i just want to edit one row.
cols="12"
class="contact-container"
v-for="contact in contacts"
:key="contact.id"
>
<b-form inline>
<b-input
type="text"
:value="contact.name"
:disabled="editMode ? disabled : ''"
/>
<b-input
type="tel"
:value="contact.phoneNumber"
:disabled="editMode ? disabled : ''"
/>
<b-input
type="email"
:value="contact.email"
:disabled="editMode ? disabled : ''"
/>
<b-input
type="text"
:value="contact.title"
:disabled="editMode ? disabled : ''"
/>
<b-button-group>
<button type="button" size="lg" class="btn">
<b-icon-x-circle-fill variant="danger"></b-icon-x-circle-fill>
</button>
<button type="button" size="lg" class="btn" #click="startEdit">
<b-icon-pencil-fill variant="primary"></b-icon-pencil-fill>
</button>
</b-button-group>
Assuming that editMode is part of the components' data. If it's a prop this solution might be a bit tricky to implement.
Set up editMode as an empty object in your component's data. And for the method startEdit it should take, as a parameter, the id of the contact being edited.
So something like this: #click="startEdit(contact.id)". and in the method body, this.$set(this.editMode, contact.id, true). See Reactivity in Depth in Vue docs for information on this.$set.
To check if a row is disabled use :disabled="editMode[contact.id]" (no need for ternary operator checking as it's a boolean)
This approach will make it possible to edit multiple rows at the same time. Though a name such as editedContacts might be better in this case.

v-select validate not working in Internet Explorer 11

Good day, how can i make v-select validate work on IE 11?
i added require('es6-promise').polyfill(); on my vue script but till i encounter error Failed to generate render function.
<v-select :options="books" label="title" v-model="selected">
<template #search="{attributes, events}">
<input
class="vs__search"
:required="!selected"
v-bind="attributes"
v-on="events"
/>
</template>
</v-select>
Solve by accessing the slot directly and binding the required attributes
<v-select :options="books" label="title" v-model="selected">
<template #search="{attributes, events}">
<input :required="!selected" aria-label="Search for option" role="combobox" type="search" autocomplete="off" class="vs__search">
</template>
</v-select>

vee validate "required" validation is working only when on change of the field

Below is my code. Three fields are there in my form. Firstname, Middlename, Lastname. All these fields are set as required one. Only difference is that "Firstname & Lastname" contains input tag, but "Middlename" contains b-form-input tag. Actually my problem is, When I focus out(blur) these("Firstname & Lastname") fields it throws an required error but when I do the same for ("Middlename") field it doesn't Image1. I have to enter the value in that ("Middlename") field Image2 ,then I removed the value it's throwing error
Image3 i.e. required validation is only working "on change" of the "("Middlename") field. What is the reason for this?
<template>
<b-card>
<h4 slot="header" class="card-title">Employee</h4>
<b-row>
<b-col sm="3">
<b-form-group>
<label for="name">First Name </label>
<input type="text" id="" class="form-control" placeholder="Enter your name" v-validate="'required'" name="Firstname">
<span v-show="errors.has('Firstname')" class="is-danger">{{ errors.first('Firstname') }}</span>
</b-form-group>
</b-col>
<b-col sm="3">
<b-form-group>
<label for="name">Middle Name </label>
<b-form-input type="text" id="" class="form-control" placeholder="Enter your name" v-validate="'required'" name="Middlename"> </b-form-input>
<span v-show="errors.has('Middlename')" class="help is-danger">{{ errors.first('Middlename') }}</span>
</b-form-group>
</b-col>
<b-col sm="3">
<b-form-group>
<label for="name">Last Name </label>
<input type="text" id="" class="form-control" placeholder="Enter your middle name" v-validate="'required|Name'" name="Lastname">
<span v-show="errors.has('Lastname')" class="help is-danger">{{ errors.first('Lastname') }}</span>
</b-form-group>
</b-col>
</b-row>
<input type="submit" value="Submit" #click="validateForm">
</b-card>
</template>
<script>
import Vue from 'vue'
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
export default {
name: 'addEmpl',
created: function() {
this.$validator.extend('Name', {
getMessage: field => '* Enter valid ' + field + '',
validate: value => /^[a-zA-Z]*$/.test(value)
});
}
}
</script>
<style lang="scss" scoped>
.is-danger{
color: RED;
}
</style>
First of all, I am also new to Vue.js and Vee-validate so I stand corrected.
The difference between the 2 fields and the middlename field is that it is a component instead of native input field.
In essence, you need to make the component behaves like an input, i.e. emits the necessary events so Vee-validate can pick up on them ('input', 'change', 'blur' etc).
For e.g if your component is a div wrapping on input it would be something like this:
<template>
<div class="myClassForDiv">
<input
type="text"
class="myClass"
#blur="$emit('blur')"
#input="$emit('input', $event.target.value)"
>
</div>
</template>
<script>
export default {
name: "b-form-input"
}
</script>
The part relevant to the question is #blur="$emit('blur')". Without this line, VeeValidate has no way of getting notified of a blur event occurring hence does not validate (I don't know what other events VeeValidate listens to by default, but 'blur' works for me and 'focusout' does not. You can always use the data-vv-validate-on directive for special events specific to your components).
You may refer to the this article by the maintainer of VeeValidate library. Notice how he creates a component that plays nicely with VeeValidate by making the component emits all the right events.
https://medium.com/#logaretm/authoring-validatable-custom-vue-input-components-1583fcc68314