Property or method "attrs" is not defined on the instance but referenced during render - vue.js

i have this error when i press a button which its inside a v-tooltip, it should sends me to anothe page in web site:
<v-tooltip bottom mg="1">
<template v-slot:activator="{ on, attrs }">
<router-link
:to="{
name: 'trabajosObservaciones',
params: { datos: item },
}"
>
<v-btn
v-bind="attrs"
v-on="on"
color="orange"
fab
x-small
dark
class="ml-2"
>
<v-icon>mdi-briefcase-eye</v-icon>
</v-btn>
</router-link>
</template>
<span>Ver Trabajos</span>
</v-tooltip>
how can i solve it?

Error is not comming from this part of your code, it's in "src/app.vue"
probably using and unregistered data property in the template

Related

Vuetify tooltip hover with link

Is it possible to have Vuetify's v-tooltip with a clickable link?
At this point using the default code provided by documentation
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon
color="primary"
dark
v-bind="attrs"
v-on="on"
>mdi-home</v-icon>
</template>
clickable link
</v-tooltip>
We can't click the anchor link because once we mouse out the icon, the tooltip automatically closes. Is this a limitation on Vuetify ?
You have 2 problems to solve:
Tooltip hides as soon as mouse leaves the activator (the icon). Just use close-delay prop set to (for example) 2000 (ms) ...so the tooltip wont disappear immediately but only after 2 seconds when you move mouse out of the icon...
By default, Vuetify tooltip's content is rendered with the pointer-events: none; CSS property. Which means the content do not generate any pointer events. Only thing you can do about it is to override the default style...
template
<v-tooltip bottom close-delay="2000">
<template v-slot:activator="{ on, attrs }">
<v-icon
color="primary"
dark
v-bind="attrs"
v-on="on"
>
mdi-home
</v-icon>
</template>
clickable link
</v-tooltip>
style
.v-tooltip__content {
pointer-events: initial;
}
Demo
You can control visibility by using v-model on the tooltip.
The following is taken from vuetifys example on visibility:
<v-tooltip
v-model="show"
top
>
<template v-slot:activator="{ on, attrs }">
<v-btn
icon
v-bind="attrs"
v-on="on"
>
<v-icon color="grey lighten-1">
mdi-cart
</v-icon>
</v-btn>
</template>
<span>Programmatic tooltip</span>
</v-tooltip>
And then define show in data:
show: false
https://vuetifyjs.com/en/components/tooltips/#visibility

Floating action button is hiding in bottom navigation bar

<v-tooltip top>
<template v-slot:activator="{ on }">
<v-btn
fab
color="green"
v-on="on"
bottom
right
fixed
:loading="isRefreshing"
#click="refreshFiles"
>
<v-icon color="white">mdi-sync</v-icon>
</v-btn>
</template>
<span>Refresh</span>
</v-tooltip>
<v-bottom-navigation v-if="isMobileViewVisible" app fixed grow shift>
<template v-for="item in menuItems">
<v-btn
v-if="item.isVisible"
:key="item.title"
icon
#click="goToRoute({ name: item.name, params: item.params })"
>
<span>{{ item.title }}</span>
<v-icon>{{ item.icon }}</v-icon>
</v-btn>
</template>
<v-btn icon #click="toProfileEdit">
<span>Profile</span>
<v-icon>mdi-account</v-icon>
</v-btn>
</v-bottom-navigation>
I am using vuejs with vuetify, I have one query where I am stuck, The issue is I am using bottom navigation bar to route to various components(pages), and each page has a floating action button in right bottom, The issue the floating action button is getting hide inside the bottom navigation bar.
Is there any idea or way on how to overcome this issue ??
Any help with example would be appreciated ..
As you can see the green button is getting hide behind bottom nav bar.
Try out to use an inline style :
<v-btn style="z-index:100; bottom:72px;" fab ...

v-list in v-list not working with vuetify

I am trying to implement list in list using vuetify. But I didnt manage to make it work. Below is the code and sample data. Please help me make it work. I am using vuetify 2.3.10. If I comment out the part for the second list then the first list works
<template>
<div>
<v-toolbar id="filter">
<v-layout row wrap>
<v-flex xs12 md1>
<v-menu attach="#filter-users" offset-y>
<template v-slot:activator="{ on, attrs }">
<div class="dropdown" v-bind="attrs" v-on="on">User</div>
</template>
<v-list id="filter-users">
<v-list-item
v-for="search_user in search_users"
#click="filterUser({user: search_user})">
<v-list-item-title>{{ search_user.name }}</v-list-item-title>
</v-list-item>
<v-list v-if="search_user.sub_users.length">
<v-list-item v-for="(search_sub_users, index) in search_user.sub_users"
:key="`sub_user_${index}`"
#click="filterUsers({user: search_sub_user})">
<v-list-item-title>{{ search_sub_user.name }}</v-list-item-title>
</v-list-item>
</v-list>
</v-list>
</v-menu>
</v-flex>
</v-layout>
</v-toolbar>
</div>
</template>
search_users demo data
search_users:[{
name: 'James',
sub_users: [
{
name: 'Willy'
},
{
name: 'Jack'
},
}]
},
name: 'Rock',
sub_users: [
{
name: 'Randy'
},
{
name: 'Amy'
},
}]
],
There's a lot of things going on in your code so let me enumerate them for you:
On your second sub-list, it can't find the search_user variable since that variable is only accessible inside the <v-list-item/>, which is outside of the <v-list/>.
What you can do is to create a <template/> that will wrap both <v-list-item/> and <v-list/> then put the v-for there. Something like this:
<v-list ...>
<template v-for="(search_user, index) in search_users">
<v-list-item :key="`user_${index}`">...</v-list-item> <!-- User List -->
<v-list :key="`sub_user_${index}`">...</v-list> <!-- Sub User List -->
</template>
</v-list>
Also, don't forget the v-bind:key, or simply :key, to the v-for's child elements.
You attempt to attach the <v-menu/> to its default slot. The attach prop of <v-menu/> should be somewhere outside the <v-menu/> or inside the its activator slot. However, it should attach directly to the element in your activator slot by default so you can just omit the attach prop.
<v-menu offset-y> <!-- remove the `attach` prop -->
<template v-slot:activator="{ on, attrs }">
<div class="dropdown" v-bind="attrs" v-on="on">User</div>
</template>
<v-list>...</v-list>
</v-menu>
On your second sub-list, you mistakenly typed search_sub_user instead of search_sub_users:
v-for="(search_sub_users, index) in search_user.sub_users"` // wrong
v-for="(search_sub_user, index) in search_user.sub_users"` // right
Here is a refactored version of your code at codesandbox.

Vuetify VTooltip trigger only on activator click

I wanted to trigger Vuetify tooltip VTooltip only when the activator is clicked rather than hovered. I tried to bind it with a variable but still triggered on hover.
methods: {
doCopy(){
// copy logic
this.showCopied = true;
setTimeout(() => {
this.showCopied = false
}, 1000)
}
}
<VTooltip v-model="showCopied">
<template #activator="{ on }">
<VBtn v-on="on" #click="doCopy"> COPY </VBtn>
</template>
</VTooltip>
This is actually more complicated than I expected thanks to some bugs. You should be able to just do <v-tooltip :open-on-hover="false">, but a focus listener is still added which causes the click to close the tooltip immediately. Instead you need to bind the click and blur events separately, and add retain-focus-on-click to the button so it doesn't blur immediately.
Full solution:
<v-tooltip bottom :open-on-hover="false">
<template #activator="{ on }">
<v-btn #click="on.click" #blur="on.blur" retain-focus-on-click>Copy</v-btn>
</template>
<span>Copy</span>
</v-tooltip>
It turns out I have to disable the default event handler of the activator.
Simply removing default event object (on) binding solves the issue.
<VTooltip v-model="showCopied">
<template #activator={}>
<VBtn #click="doCopy"> COPY </VBtn>
</template>
</VTooltip>
[UPDATED] based on #Kael Watts-Deuchar answer
NB: the v-model biding is mandatory
In vuetify 2.6.1 you can do it like this now
<v-tooltip
open-on-click
:open-on-hover="false"
>
<template
v-slot:activator="{ on }"
>
<v-btn
v-on="on"
>
button with tooltip
</v-btn>
</template>
<span>tooltip message</span>
</v-tooltip>

Meaning of v-slot:activator="{ on }"

Looking at the Vuetify example code for v-toolbar, what is the purpose of v-slot:activator="{ on }"? For example:
<template v-slot:activator="{ on }">
<v-toolbar-title v-on="on">
<span>All</span>
<v-icon dark>arrow_drop_down</v-icon>
</v-toolbar-title>
</template>
<script>
export default {
data: () => ({
items: [
'All', 'Family', 'Friends', 'Coworkers'
]
})
}
</script>
As far as I can see, on is not a defined variable anywhere, so I don't see how this is working. When I try it in my project, Internet Explorer throws an error on the <template v-slot:activator="{ on }">, but if I remove it, the page renders.
You're likely referring to this example:
<v-toolbar color="grey darken-1" dark>
<v-menu :nudge-width="100">
<template v-slot:activator="{ on }">
<v-toolbar-title v-on="on">
<span>All</span>
<v-icon dark>arrow_drop_down</v-icon>
</v-toolbar-title>
</template>
...
</v-menu>
</v-toolbar>
The following line declares a scoped slot named activator, and it is provided a scope object (from VMenu), which contains a property named on:
<template v-slot:activator="{ on }">
This uses destructuring syntax on the scope object, which IE does not support.
For IE, you'd have to dereference on from the scope object itself:
<template v-slot:activator="scope">
<v-toolbar-title v-on="scope.on">
But the ideal solution IMO is to use a Vue CLI generated project, which includes a Babel preset (#vue/babel-preset-app) to automatically include the transforms/polyfills needed for the target browsers. In this case, babel-plugin-transform-es2015-destructuring would be automatically applied during the build.
Details on the activator slot
VMenu allows users to specify a slotted template named activator, containing component(s) that activate/open the menu upon certain events (e.g., click). VMenu provides listeners for those events via an object, passed to the activator slot:
<v-menu>
<template v-slot:activator="scopeDataFromVMenu">
<!-- slot content goes here -->
</template>
</v-menu>
The slot content can access VMenu's event listeners like this:
<v-menu>
<template v-slot:activator="scopeDataFromVMenu">
<button v-on="scopeDataFromVMenu.on">Click</button>
</template>
</v-menu>
For improved readability, the scoped data can also be destructured in the template:
<!-- equivalent to above -->
<v-menu>
<template v-slot:activator="{ on }">
<button v-on="on">Click</button>
</template>
</v-menu>
The listeners from the scope object are passed to the <button> with v-on's object syntax, which binds one or more event/listener pairs to the element. For this value of on:
{
click: activatorClickHandler // activatorClickHandler is an internal VMenu mixin
}
...the button's click handler is bound to a VMenu method.
I think the original question is about understanding the "on" object. It is best explained here:
https://github.com/vuetifyjs/vuetify/issues/6866
Essentially "on" is a prop passed in from the activator. What v-on="on" does is bind that on prop to the component. "on" itself is all of the event listeners passed from the activator.
To call out a readability tip, it's possible to use this syntax:
<v-menu>
<template v-slot:activator="{ on: activationEvents }">
<v-btn v-on="activationEvents">
I like turtles 🐢
</v-btn>
</template>
</v-menu>
In my brain this has a more fluent readability than v-on="on", which to me is like observing a conversation consisting solely of:
Person 1: "Hey"
Person 2: "Yep"
Understand? ;)
By the way, activationEvents could be any alias, like "slotEvents", "listeners", "anyOldEvent", or whatever makes more sense to the reader as a renaming of the mysterious on.
Run the below code,you will know what is 'attrs' an 'on' in v-menu.
<v-menu>
<template v-slot:activator="{ on, attrs }">
<div v-bind="attrs" v-on="on">
v-menu slot activator:
<br />
attrs == {{ JSON.stringify(attrs) }}
<br />
on == {{ '{' + Object.keys(on).map(k => k + " : " + on[k]).join(',') + '}' }}
</div>
</template>
</v-menu>
Result:
v-menu slot activator:
attrs == {"role":"button","aria-haspopup":true,"aria-expanded":"false"}
on == {
click:function (e) {if (_this.openOnClick) {onClick && onClick(e);}_this.absoluteX = e.clientX;_this.absoluteY = e.clientY;},
keydown:function () { [native code] }
}
Explanation:
<div v-bind="attrs" v-on="on"> equals
<div
v-bind="{role:'button',aria-haspopup:true,aria-expanded:'false'}"
v-on="{click:function (e) {/*implement by v-menu*/},keydown:function () {/*implement by v-menu*/}}"
>
Starting in vue 2.4.0+, v-on also supports binding to an object of event/listener pairs without an argument. Note when using the object syntax, it does not support any modifiers.
Example:
<!-- v-on's object syntax (vue 2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
About <template> tags in Internet Explorer throws an error :
as vuetify docs say:
Template caveat
Due to Internet Explorer’s limited support for <template> tags, you must send fully compiled dom elements to the browser. This can be done by either building your Vue code in advance or by creating helper components to replace the dom elements. For instance, if sent directly to IE, this will fail:
<!-- Vue Component -->
<template v-slot:items="props">
<td>{‌{ props.item.name }‌}</td>
</template>