How to use vee-validate 4 (alpha) with Vuetify for validation? - vuetify.js

I am trying to use the latest alpha release of vee-validate. Is it possible to use vee-validate 4 (alpha)'s Form and Field components with Vuetify for validation?
In the example in Vuetify documentation for validation with vee-validate, it only shows use of validation-observer and validation-provider.

Here a good example for veevalidate4, vuejs3 and vuetify3 (typescript,nuxtjs and YUP):
example configuration
in practice
<template>
<div>
<v-app id="inspire">
<v-container fluid fill-height>
<v-row vertical-align="center">
<v-col lg="6" sm="12" align-self="center" offset-lg="3">
<v-card class="elevation-12">
<v-toolbar dark color="success">
<v-toolbar-title>Se connecter</v-toolbar-title>
</v-toolbar>
<v-card-text>
<Form #submit="onSubmit" :validation-schema="schema">
<Field name="username" v-slot="{ field, errors }">
<v-text-field
name="username"
label="Login"
type="email"
v-bind="field"
variant="solo"
append-inner-icon="mdi-magnify"
:error-messages="errors"
></v-text-field>
</Field>
<Field name="password" v-slot="{ field, errors }">
<v-text-field
id="password"
prepend-inner-icon="fa:fas fa-lock"
name="password"
label="Password"
v-bind="field"
type="password"
variant="solo"
:error-messages="errors"
></v-text-field>
</Field>
<v-btn
block
color="success"
size="large"
type="submit"
>
Se connecter
</v-btn>
</Form>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
</template>
<script lang="ts" setup>
const {REST_API_URL} = useRuntimeConfig();
import {Form, Field, ErrorMessage} from "vee-validate";
import * as Yup from "yup";
const schema = Yup.object().shape({
username: Yup.string().required("Email is mandatory.").email("The email
entered doesn’t seem right, please try again."),
password: Yup.string().required("Full name is mandatory."),
});
const props = defineProps({
source: String,
})
function onSubmit(values: any) {
console.log('Submitted with', values);
const {data: token, error, pending} = useFetch(REST_API_URL + '/auth/signin', {method: "POST", body: values})
}

vee-validate v4 does not support Vue 2 at the moment unless Vuetify has also released support for Vue 3 there is no way to use the two at the moment.
Supporting Vue 2 and 3 at the same time is a very hard task for complex libraries such as Vuetify and vee-validate

Related

Vuetify: How to horizontally- and vertically align a text field in a parallax

I am trying to horizontally- and vertically align a text field within a parallax in Vuetify. Doing it with text works fine as seen here (Center text in Parallax) but doing it with a text field fails (Center Textfield in Parallax).
Code:
<template>
<v-app>
<v-main>
<v-parallax src="https://cdn.vuetifyjs.com/images/backgrounds/vbanner.jpg">
<div class="d-flex flex-column fill-height justify-center align-center text-white">
<v-text-field label="Your email" clearable variant="solo" prepend-inner-icon="mdi-email-outline" min-width="350">
<template v-slot:append-inner>
<v-btn class="mt-n1" color="green">
Sign up
</v-btn>
</template>
</v-text-field>
</div>
</v-parallax>
</v-main>
</v-app>
Thanks!
Its because the text field has some flex rules on it already.
Add the flex helper class flex-grow-0 to the text field.
And add align-self-stretch to ensure the text field width changes.
To add some spacing either side, add mx-5 helper class.
<v-text-field class="flex-grow-0 align-self-stretch mx5" label="Your email" clearable variant="solo" prepend-inner-icon="mdi-email-outline" min-width="350">
Example: Link

Why isn't the v-icon displayed inside the v-text-field?

Can you tell me why the icon to the right of the v-text-field is not displayed?
I want to make the calendar open when you click on the icon.
codepen
<div id="app">
<v-app id="inspire">
<v-menu>
<template v-slot:activator="{ on }">
<v-text-field label="Hello world" style="max-width: 200px">
<!--The icon is not displayed-->
<v-icon v-on="on" color="primary" dark>event</v-icon>
</v-text-field>
</template>
<v-date-picker>
</v-date-picker>
</v-menu>
</v-app>
</div>
P.S.
Here is a good example. It's not mine.
Codepen
The HTML input field is empty https://www.w3schools.com/tags/tag_input.asp
There's an attribute to prepend and append icons in textfields in Vuetify: https://vuetifyjs.com/en/components/text-fields/#icons
You simply need to add it:
<v-text-field label="Hello world" style="max-width: 200px" append-icon="event">
I managed to do it. I did this without the activator template.
codepen vuetify
<div id="app">
<v-app id="inspire">
<v-text-field
label="Hello world"
style="max-width: 200px"
append-icon="event"
#click:append="show">
</v-text-field>
<v-menu
v-model="menu"
:position-x="x"
:position-y="y"
absolute >
<v-date-picker />
</v-menu>
</v-app>
</div>
show (e) {
console.log(123);
e.preventDefault();
this.menu = false;
this.x = e.clientX;
this.y = e.clientY;
this.$nextTick(() => {
this.menu = true
})
},

Validation reset after form submission

I've got the form with checkboxes and I want the user to select at least one of them. Everything works fine, but after resetting the form I can't hide the validation message.
This case is described exactly in the docs, but the provided solution seems to be invalid because after submitting the form validation errors show up.
<template>
<v-app>
<v-content>
<playground></playground>
<v-card class="mx-auto" outlined>
<ValidationObserver ref="obs" v-slot="{ invalid, valid, validated, passes, reset }">
<v-card-title class="pb-0">Meal types</v-card-title>
<v-row justify="center">
<v-col cols="11">
<v-form ref="form">
<ValidationProvider rules="required" v-slot="{ errors, failedRules }">
<v-container row pa-0>
<v-row justify="space-around">
<v-checkbox
v-model="mealType"
value="BREAKFAST"
label="Breakfast"
hide-details
></v-checkbox>
<v-checkbox v-model="mealType" value="DINNER" label="Dinner" hide-details></v-checkbox>
<v-checkbox v-model="mealType" value="SUPPER" label="Supper" hide-details></v-checkbox>
<v-checkbox v-model="mealType" value="SNACK" label="Snack" hide-details></v-checkbox>
</v-row>
</v-container>
<v-row justify="center">
<v-alert
v-if="failedRules.required"
type="error"
dense
outlined
class="mt-4 mb-0"
>Select at least one meal type</v-alert>
</v-row>
</ValidationProvider>
</v-form>
</v-col>
</v-row>
<v-card-actions>
<v-row justify="center">
<v-btn text color="deep-purple accent-4" #click="passes(addRecipe)">Save</v-btn>
<v-btn #click="reset">Reset</v-btn>
</v-row>
</v-card-actions>
</ValidationObserver>
</v-card>
</v-content>
</v-app>
</template>
<script>
import Playground from "./components/Playground";
export default {
name: "App",
components: {
Playground
},
data() {
return {
recipeName: "",
mealType: []
};
},
methods: {
addRecipe() {
console.log("add recipe");
// after save or reset alerts should disappear..
this.$refs.form.reset();
requestAnimationFrame(() => {
this.$refs.obs.reset();
});
}
}
};
</script>
Code Sandbox with reproduced use case: https://codesandbox.io/s/vee-validate-3-reset-checkbox-validation-qr8uw
Please select some meal types and click save. After clicking the save button, the form is reset and the validation message shows up, but it shouldn't. How to solve this?
Found a workaround, which will help you solving the issue (the original with this.$refs.form.reset()), has to be a bug, and should be reported to VeeValidate for solving.
I found out making the method async, and resetting the variable manually made it all work out.
methods: {
async addRecipe() {
console.log("add recipe");
console.log(this.mealType);
this.mealType = [];
this.$refs.obs.reset();
}
}

Set values for v-select items

I've form.blade.php file , here's it's content
<app-add-new-file-form inline-template :subjects="{{ json_encode($subjects) }}">
<v-form method="POST" action=" {{ route('files.store') }} " enctype="multipart/form-data">
#csrf
<div class="my-8">
<v-select v-model="subject" :items="subjects" :item-value="subject" name="subject" menu-props="auto"
label="Subject" hide-details single-line></v-select>
<p class="text-danger">{{ $errors->first('subject') }}</p>
</div>
</v-form>
</app-add-new-file-form>
and in my vue components I've this code below :
<script>
export default {
props: ["subjects"],
data: () => {
return {
subject: "",
};
}
};
</script>
However, when i submit the form, the subject value is set to null on any subject I select
Note : the subjects array comes from laravel then I encode it to json.
It is stated that Vuetify v-select does not have an input value. Longer answer by Vuetify dev here. They are just not setting the value to input.
The solution would be to add a hidden input that keeps the selected value and is submitted with form.
Example codepen
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
subjects: ['Subject1', 'Subject2', 'Subject3', 'Subject4'],
selectedSubject: ''
}),
})
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-row align="center">
<v-col class="d-flex" cols="12" sm="6">
<v-select
v-model="selectedSubject"
:items="subjects"
label="Subjects"
solo
></v-select>
<input type="hidden" v-model="selectedSubject" name="subject">
</v-col>
</v-row>
</v-container>
</v-app>
</div>
I included an example image where to find input value from devtools. If you check v-select input value, it is empty. Then of you check the hidden inputs value it has the selected value.
Example image where to find input value

Getting v-text-field value with xpath in Vuejs (with nightwatch)

VueJS markup:
<v-menu
lazy
:close-on-content-click="false"
v-model="modal"
transition="scale-transition"
offset-y
full-width
:nudge-right="40"
max-width="290px"
min-width="290px">
<v-text-field
slot="activator"
label="Issue Date"
v-model="date"
append-icon="event"
readonly
>
</v-text-field>
<v-date-picker v-model="date" no-title scrollable actions>
<template scope="{ save, cancel }">
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat color="primary" #click="cancel">Cancel</v-btn>
<v-btn flat color="primary" #click="save">OK</v-btn>
</v-card-actions>
</template>
</v-date-picker>
</v-menu>
HTML:
`<div class="menu__activator">
<div data-v-386ef34c="" class="input-group input-group--dirty input-group--append-icon input-group--text-field">
<label>Issue Date</label>
<div class="input-group__input">
<input readonly="readonly" tabindex="0" aria-label="Issue Date" type="text">
<i aria-hidden="true" class="material-icons icon input-group__append-icon input-group__icon-cb">event</i>
</div>
<div class="input-group__details">
<div class="input-group__messages"></div>
</div>
</div>
</div>`
How it appears in browser:
I'd like to write e2e to assert some logic with the calendar date. Date is produced with moment to match current day. However I cannot figure out how to access that text value with xpath.
Xpath to get the element:
$x('//div[contains(#class, "input-group--text-field")]//input[#readonly]')
How the element appears in developer console:
With the attribute I need at the very bottom:
Xpaths I've tried which result in empty array:
$x('//div[contains(#class, "input-group--text-field")]//input[#readonly]//#value')
$x('//div[contains(#class, "input-group--text-field")]//input[#readonly]/#value')
$x('//div[contains(#class, "input-group--text-field")]//input[#readonly][0]//#value')
Edit:
Managed to get the value in chrome console:
$x('//div[contains(#class, "input-group--text-field")]//input[#aria-label="Issue Date"]')[0].value
But still struggling with Nightwatch
Any solutions with xpath or css are welcome! Thanks!
Had to import chai, but this finally worked:
.getValue('//div[contains(#class, "input-group--text-field")]//input[#aria-label="Issue Date"]', function(result) {
expect(result.value).to.equal('2017-10-17')
})

Resources