onInvalidSubmit dose not work in vee-validate version (^4.5.2) - vue.js

I am trying to capture errors in forms and have to display them in modal. But vee-validate onInvaidSubmit seems not working. See code below.
PS: I copied this example from https://vee-validate.logaretm.com/v4/guide/components/handling-forms
Vue Version : 3, vee-validate: 4.5.11
<template>
<Form v-slot="{ validate }" :validation-schema="schema">
<Field name="email" type="email" />
<ErrorMessage name="email" />
<Field name="password" type="password" />
<ErrorMessage name="password" />
<button #click="validate">Submit</button>
</Form>
</template>
<script>
import { Form, Field, ErrorMessage } from 'vee-validate'
import * as yup from 'yup'
export default {
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object({
email: yup.string().required().email(),
password: yup.string().required().min(8),
})
return {
schema,
}
},
methods: {
onSubmit(values) {
// Submit values to API...
alert(JSON.stringify(values, null, 2))
},
onInvalidSubmit({ values, errors, results }) {
console.log(values) // current form values
console.log(errors) // a map of field names and their first error message
console.log(results) // a detailed map of field names and their validation results
},
},
}
</script>

try the following by adding it to the Form element. see below
<Form v-slot="{ validate }" :validation-schema="schema" #invalid-submit="onInvalidSubmit">
<Field name="email" type="email" />
<ErrorMessage name="email" />
<Field name="password" type="password" />
<ErrorMessage name="password" />
<button #click="validate">Submit</button>
</Form>

Related

vuejs: ref tag in dom element not work when use with object attribute

With this code:
<script setup lang="ts">
import { ref } from "vue"
const input1 = ref(null)
const group = {
input2: ref(null),
input3: ref(null),
}
function main() {
console.log("input1", input1?.value?.value)
console.log("input1", group.input3?.value?.value)
console.log("input3", group.input3?.value?.value)
document.getElementsByTagName("textarea")[0].value = `
input1: ${input1?.value?.value}
input2: ${group.input2?.value?.value}
input3: ${group.input3?.value?.value}
`.trim()
}
</script>
<template>
<input ref="input1" type="text" value="1" />
<input ref="group.input2" type="text" value="2" />
<input ref="group.input3" type="text" value="3" />
<button #click="main">click</button>
<p>
<textarea cols="30" rows="6"></textarea>
</p>
</template>
when you do click, you get input1 in input1.value, but yo don't get input2 and input3 in group.input2.value and group.input3.value, you get null instead.
Why input1.value works but group.input2.value and group.input3.value are always null?
How can I defined a one single object with one attribute for each input?
What I am really want to achieve is a single object that represent all inputs in a form.

Library Vee-validate "rules" are not working in VueJS app

I am using vee-validate 4.5.8 with vue.js 3.2.13.
Imported modules into component
import { Field, Form, ErrorMessage, defineRule } from "vee-validate";
import { required, email, alpha_spaces } from "#vee-validate/rules";
defineRule("required", required);
defineRule("email", email);
defineRule("alpha_spaces", alpha_spaces);
Problem is, that "email" and "required" are working fine, but "alpha_spaces" are not detecting numbers entered.
form looks like this:
<field
name="firstname"
type="text"
placeholder="first name"
rules="required|alpha_spaces"
v-model="newUser.firstname"
/>
<ErrorMessage name="alpha_spaces" />
<field
id="email"
name="email"
type="email"
placeholder="e-mail"
rules="required|email"
v-model="newUser.email"
/>
<ErrorMessage name="email" />
question is: what i am missing?

How to use flatpickr with vee-validation in vuejs

i have use it but date not selected on first click, used version is "vue": "2.x","vue-flatpickr-component": "^8.1.6",
and my code is:
<b-form-group class="requied_field showOnCheck"
:label="$t('Start On')"
label-for="v-autoresponder_start_date"
:description="$t('start_on_desc')">
<validation-provider
#default="{ errors }"
:name="$t('Start On')"
rules="required">
<b-input-group class="input-group-merge">
<b-input-group-prepend is-text>
<feather-icon icon="CalendarIcon" />
</b-input-group-prepend>
<flat-pickr
v-model="formData.autoresponder_start_date"
:disabled="isDisabledField"
class="form-control"
id="v-autoresponder_start_date"
:config="{ defaultDate:'today',enableTime:true, minDate:'today', maxData:formData.autoresponder_end_date, dateFormat: 'Z', altInput: true}"
/>
</b-input-group>
<small class="text-danger">{{ errors[0] }}</small>
</validation-provider>
Please anyone solve the problem.
Add your config inside data function
export default {
data () {
return {
dateConfig:
{
defaultDate:'today',
enableTime:true,
minDate:'today',
maxData:formData.autoresponder_end_date,
dateFormat: 'Z',
altInput: true
}
}
},
}
Use as follows
<flat-pickr
v-model="formData.autoresponder_start_date"
:disabled="isDisabledField"
class="form-control"
id="v-autoresponder_start_date"
:config="dateConfig"
/>

VeeValidate 4 Field Validation State

I'm trying to imitate Bootstrap form validation styling with Vue and Vee-validate.
In order to have that Boostrap validation error message, when there's a validation error, the input itself must have is-invalid class presents. And in addition, the error message element must have invalid-feedback class, of course.
I'm struggling to add is-invalid class to the input when there's a validation error.
In Vee-validate 3, I was able to control the input element's classes with this guide. But it seems to be deprecated.
This is a code sandbox that you can play with. Nothing extra-ordinary, just straight out of Veevalidate example.
<template>
<div id="app">
<Form #submit="onSubmit">
<Field name="email" type="email" :rules="validateEmail" class="form-control"/>
<ErrorMessage class="invalid-feedback" name="email" />
<button class="btn btn-primary">Sign up</button>
</Form>
</div>
</template>
<script>
import {
Form,
Field,
ErrorMessage
} from "vee-validate";
export default {
components: {
Form,
Field,
ErrorMessage,
},
methods: {
onSubmit(values) {
console.log(values, null, 2);
},
validateEmail(value) {
// if the field is empty
if (!value) {
return "This field is required";
}
// if the field is not a valid email
const regex = /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
if (!regex.test(value)) {
return "This field must be a valid email";
}
// All is good
return true;
},
},
};
</script>
<style>
span {
display: block;
margin: 10px 0;
}
</style>
Versions
"vee-validate": "^4.5.11",
"vue": "^3.2.33",
You can render more complex fields, by utilizing the scoped slots of the <Field />-component.
If you replace your Field-component with the following, it should work as expected:
<Field name="email" :rules="validateEmail" v-slot="{ field, errors }">
<input v-bind="field" type="email" :class="{'is-invalid': !!errors.length }" />
</Field>

Vue.js and Vee Validate - How to update error message with error from an API

I am trying to set the error message from the vee-validate to one from an API.
<div class="col-md-12">
<label for="company-contact-name" class="label-input">Company Contact Name</label>
<input v-validate="validations.user.name" v-model="data.user.name" id="company-contact-name" class="form-control" type="text" name="name" placeholder="Enter contact name" />
<div id="name-error" class="msg-error text-danger">{{ errors.first('name') }}</div>
</div>
<div class="col-md-12">
<label for="email" class="label-input">E-mail address</label>
<input v-validate="validations.user.email" v-model="data.user.email" id="email" class="form-control" type="email" name="email" placeholder="Enter e-mail" />
<div id="email-error" class="msg-error text-danger">{{ errors.first('email') }}</div>
</div>
So, If the API returns an email error, I would like to edit the above "errors.first('email')" to the API error. Then, when the user starts to correct the field, the Vee Validate would show its configured errors.
This is an example of a possible array of errors:
[
{id: "name", title: "Name is invalid. It should have only letters"},
{id: "name", title: "Name is too short. It should have more than three characters"},
{id: "email", title: "Email has already been taken"}
]
What can be done to handle the API error messages?
Thanks for your time and attention.
Perhaps something like this - create a new validator which checks whether the API has returned an error message and if yes - returns that error message. Then use this new validator as a first validator for your field, but also add the built-in validator for email addresses.
<input
v-validate="api_email|email"
v-model="user.email"
id="email"
class="form-control"
type="email"
name="email"
placeholder="Enter e-mail" />
<script>
import { Validator } from 'vee-validate';
export default
{
data()
{
api_error: '',
user:
{
email: ''
}
},
mounted()
{
Validator.extend('api_email',
{
getMessage: this.emailError,
validate: this.validateEmail
});
},
methods:
{
validateEmail(value, args)
{
return !this.api_error;
},
emailError(field, args)
{
return this.api_error;
}
}
}
</script>
UPDATE
If you want to support an array of errors then perhaps you can do it like this
<div id="email-error" class="msg-error text-danger" v-for="err in [errors.first('email')].concat(array_with_api_errors.map(item => item.title))">{{ err }}</div>