Datepicker in vuetify with validators - vue.js

I need to create a new component that only have a datepicker with his validators. This component is generic because I need to use in more components easily. I need that when you click into the datepicker and you don't pick any date show a red validation like this:
and then:
If you pick any date, this validation should disappear.
I had thinked in this form:
<ValidationObserver v-slot="{ handleSubmit, invalid }" ref="form">
<v-form #submit.prevent="handleSubmit(submit)">
<ValidationProvider ref="form" :name="nombre" :rules="rules" v-slot="{ errors }">
<v-menu v-model="dialogOpen" :close-on-content-click="false" :nudge-right="40" transition="scale-transition"
offset-y min-width="auto">
<template v-slot:activator="{ on, attrs }">
<v-text-field :error-messages="errors" v-model="value" :label="label" prepend-icon="mdi-calendar" v-bind="attrs" v-on="on">
</v-text-field>
</template>
<v-date-picker required v-model="value" #input="dialogOpen = false" #change="changed"
#keydown="checkValidate"></v-date-picker>
</v-menu>
</ValidationProvider>
</v-form>
But this doesn't work. Someone can share me another example or solution for this thing?
Thanks!

The problem is that vee-validate (v3) uses v-model to find the input tags, and since vuetify uses v-model for various components to compose them together like the date-picker, vee-validate will validate the menu instead of the v-text-field.
There is a workaround, you need to wrap the Vuetify's picker snippet in a new component DatePicker.vue
<v-menu v-model="dialogOpen" :close-on-content-click="false" :nudge-right="40" transition="scale-transition" offset-y min-width="auto">
<template v-slot:activator="{ on, attrs }">
<v-text-field :error-messages="errors" v-model="value" :label="label" prepend-icon="mdi-calendar" v-bind="attrs" v-on="on">
</v-text-field>
</template>
<v-date-picker required v-model="value" #input="dialogOpen = false" #change="changed" #keydown="checkValidate"></v-date-picker>
</v-menu>
Note that you still need to implement v-model support for this new component by emitting input event when value changes.
And then use the custom DatePicker with the ValidationProvider:
<ValidationProvider ref="form" :name="nombre" :rules="rules" v-slot="{ errors }">
<DatePicker v-model="value" />
</ValidationProvider>
Of course that was a shortsight on vee-validate's part, and the new v4 release for Vue 3 avoids this bad design.

Related

How do I pass v-on/v-bind to component

I am working with Vuetify menu and button components. I am trying to pass the menu and attrs from the activator slot in the template in SomeFile.vue into the v-btn in the MyCustomButtonTemplate.vue file, but I cannot figure out how to do it. Does anyone know how to correctly pass those values? A bare bones example is shown below
SomeFile.vue
<v-menu offset-y>
<template v-slot:activator="{ on: menu, attrs }">
<MyCustomButtonTemplate v-on="menu" v-bind="attrs">
</template>
<v-list>
<v-list-item>
<v-list-item-title>Some Title</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
MyCustomButtonTemplate.vue
<template>
<v-tooltip top>
<template #activator="{ on: tooltip }">
<v-btn v-on="{...tooltip, ...menu}" v-bind="attrs">Blah</v-btn>
</template>
<span>Some tooltip</span>
</v-tooltip>
</template>
You can access component event listeners and attributes in $listeners and $attrs objects. Also you can pass them to children with additional event handlers and listeners by destructuring them.
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-btn v-on="{ ...on, ...$listeners }" v-bind="$attrs">Blah</v-btn>
</template>
<span>Some tooltip</span>
</v-tooltip>
Here is the working codesandbox
First of all you need to make inheritAttrs to false in custom component, because by default vue for bindings will apply to the root element of the child component as normal HTML attributes.
<script>
export default {
inheritAttrs: false,
}
</script>
then you can apply attributes and listeners on your element in custom component.
<template>
<v-tooltip top>
<template #activator="{ on: tooltip }">
<v-btn v-on="{ ...tooltip, ...$listeners }" v-bind="$attrs">Blah</v-btn>
</template>
<span>Some tooltip</span>
</v-tooltip>
</template>
BTW you didnt define menu and attrs as props but you used it like you have it in your component. Most of reserved methods and properties that we use in vue starts with $. Of course this is true only for Options API.

Converting Vuetify 1.x v-slot activator to 2.x via v-data-table

I have a piece of working code from Veutify 1.5.6 that includes an icon inside of a data table that, when clicked, displays a menu. When clicked the activator shows the list that was activated.
I have a codepen with this example
I want the same functionality, but Vuetify 2 does not have slot="activator".
It looks like they use v-slot:activator="{ on }" with a template tag, but I can't get this replicated over.
This is my attempt at it.
<v-data-table
:headers="labels"
:items="data"
>
<template v-slot:[`item.statusIcon`]="{ item }">
<td style="cursor: pointer;">
<v-icon :class="item.status">{{item.statusIcon}}
<template v-slot:activator="{ on }">
<v-list>
<v-list-item
v-on="on"
v-for="(status, index) in statusItems"
:key="index"
:class="status.title"
#click="setStatus(item, status.title)"
>{{ status.title }}></v-list-item>
</v-list>
</template>
</v-icon>
</td>
</template>
</v-data-table>
There's definitely something small I'm missing and I know that the v-icon should be under the template, but I keep getting this error
'v-slot' directive must be owned by a custom element, but 'td', 'div', 'template' is not
I found this thread, but still no help.
Any help would be appreciated
You should wrap the icon with v-menu component then use this icon as menu activator :
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<v-icon v-on="on" :class="item.status">{{item.statusIcon}}
</v-icon>
</template>
<v-list>
<v-list-item
v-for="(status, index) in statusItems"
:key="index"
:class="status.title"
#click="setStatus(item, status.title)"
>{{ status.title }}></v-list-item>
</v-list>
</v-menu>

Can't Select Customized Combobox Items (Vuetify)

Two problems that I'm having with Vuetify's combobox:
Input is cleared on blur (combobox not focused on) and I don't want this. This doesn't happen if I don't customize how my items look with v-slot:item though.
Can't select any of the items when I'm trying to customize my items with v-slot:item, but I can select them if I don't customize the items.
I don't know what I'm doing wrong when I basically just copied straight from the documentation and adjusted it to my needs.
<v-combobox
#focus="isShaped = true"
#blur="isShaped = false"
v-model="card_name"
:loading="isLoading"
:items="cards"
hide-no-data
prepend-inner-icon="mdi-magnify"
append-icon=""
outlined rounded :shaped="isShaped"
label="Search for a card"
:search-input.sync="search"
item-text="name"
item-value="set_name"
>
<template v-slot:item="{ item }">
<v-list-item>
<v-list-item-content>
<v-list-item-title class="mb-2">{{item.name}}</v-list-item-title>
<v-list-item-subtitle>{{item.set_name}}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
<template v-slot:selection="{ item }">
<span v-text="item.name"></span>
</template>
<template v-slot:progress>
<v-progress-circular
class="mt-3"
v-if="isLoading"
indeterminate
color="primary"
:width="2"
:size="30"
></v-progress-circular>
</template>
</v-combobox>
Here's the codepen: https://codepen.io/chataolauj/pen/RwwYxBg?editors=1010

Display tooltip icon right after the label using vuetify

I am using the Vuetify Tooltip component. I want to display the tooltip icon right after the label. I am not sure how can I do that. Please help me figure that out. Right now the icon appears as in image 1
I want it right after the information text.
<v-container fluid>
<v-layout row wrap>
<v-flex xs11 md6 class="add-col-padding-right">
<v-text-field
label='Information'
v-model='dummy.info'
>
</v-text-field>
</v-flex>
<v-flex xs1 md6 class="add-col-padding-left">
<v-tooltip attach>
<a href='javascript:void(0);' slot="activator">
<i class="material-icons icon-black">
info
</i>
</a>
<span>Please enter the user information correctly.</span>
</v-tooltip>
</v-flex>
</v-layout>
</v-container>
Update
<v-text-field
label='Information'
v-model='dummy.info'
>
<template v-slot:append>
<v-tooltip bottom>
<template #activator="{on}">
<v-icon v-on="on">mdi-pencil</v-icon>
</template>
</v-tooltip>
</template>
</v-text-field>
Update 2
If I put v-tooltip inside then it doesn't work. I want the icon to after right after information.
<v-tooltip right>
<v-icon slot="activator" dark color="primary">info</v-icon>
<span>Please enter the user information correctly.</span>
</v-tooltip>
<v-text-field
label='Information'
v-model='dummy.info'
>
</v-text-field>
Use the append slot for the v-text-field component. Inside of the v-text-field component, this should work for you:
<template v-slot:append>
<v-tooltip bottom>
<template #activator="{on}">
<v-icon v-on="on">mdi-pencil</v-icon>
</template>
<v-tooltip>
</template>
Edit: You may not have material design icons configured with Vuetify like I do.
Try this, sorry about the confusion.
<v-text-field>
<template v-slot:append>
<v-tooltip bottom>
<template v-slot:activator="{on}">
<v-btn v-on="on">test</v-btn>
</template>
<span>Hello World</span>
</v-tooltip>
</template>
</v-text-field>
This should put a v-btn at the end of the text field with a tooltip that reads 'Hello World'

Switching child components inside v-data-table using buttons(filters)

I have a parent component with 2 buttons that I want to use as filters. the child component is called inside a v-data-table.
ScanGrid(parent):
<template>
<v-card class="ma-5" v-else>
<v-flex row xs12 class="pa-3 ml-3">
<div class="mr-3 mt-2">
<h3>Regrouper par :</h3>
</div>
<div>
<v-btn-toggle color="success" v-model="groupBy">
<v-btn
text
value="barCode"
class="lowerCase"
v-ripple="{ class: 'success--text' }"
>
Code barre
</v-btn>
<v-btn
text
value="productDef"
class="lowerCase"
v-ripple="{ class: 'success--text' }"
>
Définition de produit
</v-btn>
</v-btn-toggle>
</div>
</v-flex>
<v-card-text>
<v-layout align-center>
<v-data-table
:headers="headers"
:items="items"
item-key="StorageName"
show-expand
single-expand
:expanded="expanded"
hide-default-footer
#click:row="clickedRow"
>
<template v-slot:expanded-item="{ item }">
<td :colspan="12">
<ScanGridCode :item="item"></ScanGridCode>
</td>
</template>
<template v-slot:expanded-item="{ item }">
<td :colspan="12">
<ScanGridDef :item="item"></ScanGridDef>
</td>
</template>
</v-data-table>
</v-layout>
</v-card-text>
</v-card>
</template>
The children components I want to switch using the buttons are called ScanGridCode and ScanGridDef inside templates in v-data-table. I tried to find examples of filtering buttons online but couldn't find anything like what I want to do.
I'm using Vue 2.6.10 with Vuetify 2.1.7
You're almost done already, since you already have the v-btn-toggle set up with v-model="groupBy". All you still need is to add v-if to each template, like:
<template v-if="groupBy=='barCode'" v-slot:expanded-item="{ item }">