Vuetify tooltip doesn't show up in the DOM - vue.js

When pasting the docs' example in my component's template:
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn color="primary" dark v-on="on">Button</v-btn>
</template>
<span>Tooltip</span>
</v-tooltip>
... I get this in the DOM:
<span data-v-26084dc2="" class="v-tooltip v-tooltip--top"></span>
This is how I import Vuetify in my main.js:
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify);
Using Vue 2.5.17 and Vuetify 1.3.15

v-slot was introduced in Vue 2.6.0. You'll need to use the older slot
syntax with 2.5.17 and use it directly on <v-btn> element
vuejs.org/v2/guide/components-slots.html#Deprecated-Syntax
slot attribute can also be used directly on a normal element
<v-tooltip bottom>
<v-btn slot="activator" color="primary" dark>Button</v-btn>
<span>Tooltip</span>
</v-tooltip>

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>

Datepicker in vuetify with validators

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.

Using v-tooltip inside v-menu activator in vuetify 2.0

How to use v-tooltip inside v-menu activator with vuetify 2.0? Previously it was working using slot="activator".
That's what I'm trying to combine:
<v-menu>
<template v-slot:activator="{on}">
<v-btn v-on="on">Menu Trigger</v-btn>
</template>
...list with menu options...
</v-menu>
and
<v-tooltip v-slot:activator="{on}">
<v-btn v-on="on">Menu Trigger with Tooltip</v-btn>
<span>Tooltip Content</span>
</v-tooltip>
Now I try to paste v-tooltip inside v-menu, what should happen with {on} here?
I think you're most likely unsure about the "conflicted" on objects passed to the template by multiple activator slots and how to apply all of the event handlers on the target element(s).
If that's the case, you can workaround this by assigning either one (or both) of them to a variable with a different name (see: assigning to new variable names), and then destructure and "restructure", which basically glues them back together (or merge them, technically speaking).
<v-menu>
<template #activator="{ on: onMenu }">
<v-btn v-on="onMenu">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="{ on: onTooltip }">
<v-btn v-on="{ ...onMenu, ...onTooltip }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<!-- ...list with menu options... -->
</v-menu>
Or, use the slot props directly. Just make sure to name them properly so they won't introduce another naming conflict with the component's data and/or props.
<v-menu>
<template #activator="menu">
<v-btn v-on="menu.on">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="tooltip">
<v-btn v-on="{ ...menu.on, ...tooltip.on }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<!-- ...list with menu options... -->
</v-menu>
Complete Demo:
new Vue({
el: '#app',
data: () => ({
items: [
{ title: 'Item #1' },
{ title: 'Item #2' },
{ title: 'Item #3' }
]
})
})
<link href="https://fonts.googleapis.com/css?family=Roboto:400|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.x/dist/vuetify.js"></script>
<div id="app">
<v-menu>
<template #activator="{ on: onMenu }">
<v-btn v-on="onMenu">Menu Trigger</v-btn>
<v-tooltip bottom>
<template #activator="{ on: onTooltip }">
<v-btn v-on="{ ...onMenu, ...onTooltip }">Menu Trigger with Tooltip</v-btn>
</template>
<span>Tooltip Content</span>
</v-tooltip>
</template>
<v-list>
<v-list-tile
v-for="(item, index) in items" :key="index"
#click.prevent>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>

Can a ui component be an activator for two items? (Trying to use a v-tooltip with a v-dialog)

I have a button that is the activator for a dialog in my template. But I also want to use a tooltiop with the button. (Said otherwise, when I hover over the button I'd like to see the v-tooltip and when I click the button I'd like to open the dialog.)
I've tried to use the "append" slot on the tooltip but no success. When I add the append slot, the button completely vanishes from the rendered page.
Is it even possible to use a v-tooltip with a v-dialog in veutify?
This is what I have that does not work.
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<v-app>
<v-dialog v-model="showAddPopup" persistent max-width="600px">
<v-tooltip slot="append" bottom>
<v-btn slot="activator" absolute fab dark left color="primary" #click="showPopup=true">
<v-icon dark>add</v-icon>
</v-btn>
<span>Tooltip</span>
</v-tooltip>
<app-add-new-evaluator-modal #closePopup="closePopup($event)" #submit="addNewEvaluator" />
</v-dialog>
</v-app>
The Vuetify docs explain how to do this, but you'll find it in the Menu Component:
https://vuetifyjs.com/en/components/menus#menu-with-activator-and-tooltip
Here's a simple example which opens a dialog with a button that has a tooltip:
<v-dialog>
<template #activator="{ on: dialog }">
<v-tooltip>
<template #activator="{ on: tooltip }">
<v-btn v-on="{ ...tooltip, ...dialog }">Button</v-btn>
</template>
<span>Tooltip text</span>
</v-tooltip>
</template>
<v-card>
Dialog content
</v-card>
</v-dialog>
Thanks #Traxo. All I had to do was add the slot="activator"to both components for it to work.
⚠️ ⚠️ problem with this solution, menu gets closed when you click anywhere on it ⚠️ ⚠️
Use this only if you can afford it to close anywhere you click:
<template>
<v-menu>
<template v-slot:activator="{ on: menu, attrs }">
<v-tooltip bottom>
<template v-slot:activator="{ on: tooltip }">
<v-btn v-bind="attrs" v-on="{ ...tooltip, ...menu }" fab>
<v-icon>mdi-account-multiple-plus</v-icon>
</v-btn>
</template>
<span>tooltip</span>
</v-tooltip>
</template>
<v-card>
<v-card-title class="headline grey lighten-2">
title
</v-card-title>
<v-card-text>
text
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text #click="dialog = false">
I accept
</v-btn>
</v-card-actions>
</v-card>
</v-menu>
</template>