Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Documentation] v-slot:activator="{ on }" #6866

Closed
YuqiaoS opened this issue Mar 29, 2019 · 48 comments
Closed

[Documentation] v-slot:activator="{ on }" #6866

YuqiaoS opened this issue Mar 29, 2019 · 48 comments
Assignees

Comments

@YuqiaoS
Copy link

YuqiaoS commented Mar 29, 2019

https://vuetifyjs.com/en/components/tooltips#usage

<v-tooltip bottom>
      <template v-slot:activator="{ on }">
        <v-icon color="primary" dark v-on="on">home</v-icon>
      </template>
      <span>Tooltip</span>
</v-tooltip>

So I'm guessing that the activator slot in the component binds the data object from the render function so that its available in the parent scope. The data object contains an on property which includes the event listeners.

It'd be nice for the doc to provide some pointers to the logic and syntax used. A brief comment in the activator slot description with a link to the below url would be nice.

https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth

Originally posted by @YuqiaoS in #6823 (comment)

@dsseng
Copy link
Contributor

dsseng commented Mar 29, 2019

@YuqiaoS No, it binds slot scope (values that are passed to slot scope), not all data.

@dsseng dsseng closed this as completed Mar 29, 2019
@dsseng dsseng added invalid The issue is missing information or is not a valid bug/feature request T: question A question that does not match a bug or feature request upstream Problem with a third party library that we may have to work around labels Mar 29, 2019
@YuqiaoS
Copy link
Author

YuqiaoS commented Mar 29, 2019

This isn't clear at all. You should add doc to explain what the syntax means.

@dsseng
Copy link
Contributor

dsseng commented Mar 29, 2019

@YuqiaoS
Copy link
Author

YuqiaoS commented Mar 30, 2019

But that doesn't tell you that there's the "on" property that the slots pass to the parents that contains some built in listeners that you don't know of.

@dsseng
Copy link
Contributor

dsseng commented Mar 30, 2019

Scoped slot passes things that are passed by component

@dsseng
Copy link
Contributor

dsseng commented Mar 30, 2019

All v-tooltip slots aren't scoped, you can't get anything from them via this method

@jacekkarczmarczyk
Copy link
Member

And you don't know what component passes to the slot if you don't read the source code, I agree that there should be explained what data is passed, probably in slots section
@sh7dm activator slot is (can be) scoped

@jacekkarczmarczyk jacekkarczmarczyk added T: documentation and removed T: question A question that does not match a bug or feature request invalid The issue is missing information or is not a valid bug/feature request upstream Problem with a third party library that we may have to work around labels Mar 30, 2019
@malipetek

This comment has been minimized.

@garyo

This comment has been minimized.

@johnleider johnleider changed the title v-slot:activator="{ on }" [Documentation] v-slot:activator="{ on }" Apr 1, 2019
@yuminatwca
Copy link

yuminatwca commented Apr 22, 2019

this v-on="on" confuses me so so much.

I have been digging Vuejs Documentation for a long time and no luck. I don't know what it means.

I thought v-on:click is the common usage, or @click.

So, what the heck is v-on="on" ? what is on ?

@MajesticPotatoe
Copy link
Member

@yuminatwca if you look at at the example you will see that on is a prop passed in from the activator. all v-on="on" is doing is bind that on prop to the component. on itself is all of the event listeners passed from the activator.

@jacekkarczmarczyk
Copy link
Member

I have been digging Vuejs Documentation for a long time and no luck

Also this can be reported in vue docs repo

@KaelWD
Copy link
Member

KaelWD commented Apr 23, 2019

https://vuejs.org/v2/api/#v-on

@garyo
Copy link

garyo commented Apr 23, 2019

The question is not (I think) what "v-on" means; that's standard Vue. The question is why do I have to pass something called "on" around just to get a tooltip. My component doesn't have anything called "on", so what is the "on" object, why is it needed, is that name part of the API or is it arbitrary, is it useful to me or is it just boilerplate? These are the questions at hand I think.

@yuminatwca
Copy link

According to vuejs documentation, a new syntax has been introduced since 2.4.0+:

<!-- object syntax (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

But, what is confusing is v-on={ on }.

OK, here is the question: on what? on which event triggered ?

@emjayess
Copy link

emjayess commented May 1, 2019

The question is not (I think) what "v-on" means; that's standard Vue. The question is why do I have to pass something called "on" around just to get a tooltip. My component doesn't have anything called "on", so what is the "on" object, why is it needed, is that name part of the API or is it arbitrary, is it useful to me or is it just boilerplate? These are the questions at hand I think.

Accurate.

I attempted to implement a date picker yesterday, adhering to the samples provided, and it was breaking on this mysterious "on" construct; only guessing as to why, I decided it must be time to drag my vue and vuetify packages up to latest versions. (Several hours of dependency mazes later) I got it working.

so what is the "on" object, why is it needed, is that name part of the API or is it arbitrary, is it useful to me or is it just boilerplate?

Fwiw, it does evidently only function with v-slot:activator="{ on }" and v-on="on" explicitly; when I tried v-slot:activator="{ onit }" and v-on="onit", it would not function.

@renetik
Copy link

renetik commented May 24, 2019

Up until I have seen this, I was thinking vuetify makes readable codebase ;)

@renetik
Copy link

renetik commented May 24, 2019

Far better to write it like this if possible

            <v-tooltip bottom v-for="(link, index) in project.links">
              <v-btn :href="link.url" :key="index" class="mx-3" icon
                     slot="activator" style="color: var(--primary-color)" target="_blank">
                <v-icon size="50px">{{ link.icon }}</v-icon>
              </v-btn>
              <span>{{link.tip}}</span>
            </v-tooltip>

@DRoet
Copy link
Contributor

DRoet commented May 24, 2019

sure but slot="activator" won't work anymore in vuetify 2.0

@tkharuk
Copy link

tkharuk commented Jul 3, 2019

Offtopic, but kinda related since this thread is caused by complexity and confusion...

Is it super crazy to desire a simple version of tooltips?

<v-tooltip tooltip="Text">
   <v-icon>home</v-icon>
</v-tooltip>

Simple text content on hover is, probably, the most common usage of a component.

@garyo
Copy link

garyo commented Jul 3, 2019

Actually if you use the 'v-tooltip' npm module at https://www.npmjs.com/package/v-tooltip, it has even simpler syntax because it's just a directive:

              <v-icon @click="logOut"
                      v-tooltip='"Log out"'>
                logout
              </v-icon>

It's not totally material-design but you can style it pretty well.

@tkharuk
Copy link

tkharuk commented Jul 3, 2019

@garyo that is a nice example of how a simple tooltip could be declared!
Yet, I'd like to stick to a chosen library as much as possible. Standalone packages tend to have their own merits (in v-tooltip case it is unjustified bundle weight).

So, hopefully, tooltip API will be simpler one day.
Maybe it is worth opening a new thread and start working towards API simplification.
Even though this conversation seems to go in circles - #2961

@elasticdotventures
Copy link

💀 Important to note the example :

  <v-dialog v-model="visible">
    <template v-slot:activator="{ on: { click } }">
      <v-btn v-on:click="click">

uses "click"; it is not same:same
it would not work on a phone or device without a mouse potentially creating a poor inconsistent across device user experience ( ... so hopefully that's what you wanted). ❤🐭 cheers!

@jacekkarczmarczyk
Copy link
Member

@elasticdotventures What exactly doesn't work? https://codepen.io/anon/pen/voYNwb

@MajesticPotatoe MajesticPotatoe self-assigned this Aug 2, 2019
@mcanyucel
Copy link

After reading all the messages above, I still have some confusion 😕 .
I have two nested elements both having activators:

<v-card>
      <v-card-text>
        <v-tooltip bottom>
          <template v-slot:activator="{ on }">
            <v-layout align-center row wrap mx-2 v-on="on">
              <!-- a bunch of v-flex here that I removed for ease of reading -->
              <v-flex pl-5 md12 lg1>
                <v-dialog v-model="dialog" max-width="344">
                  <template v-slot:activator="{on}">
                    <v-btn outlined class="mr-2 blue accent-1" v-on="on">Rate</v-btn>
                  </template>
                  <RateComponent :calculator="calculator" v-bind:dialog.sync="dialog" />
                </v-dialog>
              </v-flex>
            </v-layout>
          </template>
          <span>Click RATE button on the right to rate this calculator</span>
        </v-tooltip>
      </v-card-text>
    </v-card>

So everything is under <v-tooltip> with an activator on that is bound to the v-on of <v-layout>, which includes the <v-dialog> also having an activator on bound to the v-on of <v-btn> under the very same <v-layout>. Now don't get me wrong, everything is working as it should be; the dialog is not shown on hovering the <v-layout>, nor the dialog has the tooltips displayed on hovering. But I am not sure why it works as it should. My instinct says "do not touch if it ain't broke" but my curiosity keeps poking my head 😃

@kaaposc
Copy link

kaaposc commented Aug 22, 2019

@mcanyucel
For nested activators it's better to name them somewhat context-wise, like

<v-tooltip>
  <template v-slot:activator="{ on: tooltip }">
    <v-layout v-on="tooltip">
      <v-dialog>
        <template v-slot:activator="{ on: dialog }">
          <v-btn v-on="dialog">Rate</v-btn>
        </template>
      </v-dialog>
    </v-layout>
  </template>
  <span>Tooltip text</span>
</v-tooltip>

As for why your example is working, consider this example:

const on = {
  click: () => {
    console.log('Outer scope')
  }
}

on.click()    // --> 'Outer scope'

const inner = () => {
  const on = {
    click: () => {
      console.log('Inner scope')
    }
  }
  
  on.click()
}

inner()    // --> 'Inner scope'
on.click()  // --> 'Outer scope'

(read more about scopes)

@elasticdotventures
Copy link

elasticdotventures commented Aug 24, 2019 via email

@jacekkarczmarczyk
Copy link
Member

That was 1.x example, here is updated to 2.0 https://codepen.io/jkarczm/pen/oNvBrar
You need to press tab twice though, because of some other bug

@aislanmaia
Copy link

aislanmaia commented Dec 16, 2019

How can I use this v-on activator (for v-menu) for hover events ??

This is confusing as hell. To click event, this "syntax" vuetify team has choosen works out-of-box.. but when we need hover, this is complicated, when this should not be.

@Vercadium
Copy link

Vercadium commented Feb 11, 2020

@aislanmaia you can use the open-on-hover prop on v-menu.

On the larger debate, I can appreciate both sides. On one hand, having an intuitive syntax is fantastic and is part of what makes working with Vue so great; on the other you have syntax that is a little cryptic but elegant and flexible enough for it to be used consistently throughout Vuetify.

Ultimately, we live in an ecosystem of abstractions where you don't have to understand everything to accomplish your goal. Stop to consider how many other dependencies you use without understanding what goes on under the hood.

Therefore, in my opinion I wouldn't change the syntax. That said, while I don't feel explaining this is necessary for consumption, for the majority of users it is at the very least a repeating pattern that Vuetify is a proponent of. I think we could help users of Vuetify by providing a short breakdown of this somewhere in the documentation.

@pdcmoreira
Copy link

There is no example of how to capture the events to do our own actions with this syntax.
I would guess we should do something like:

<v-tooltip bottom>
  <template #activator="{ on }">
    <v-btn icon v-on="{ ...on, click: openSettings }">
      <v-icon>mdi-settings</v-icon>
    </v-btn>
  </template>

  <span>Settings</span>
</v-tooltip>

or

<v-tooltip bottom>
  <template #activator="{ on }">
    <v-btn icon v-on="on" @click="openSettings">
      <v-icon>mdi-settings</v-icon>
    </v-btn>
  </template>

  <span>Settings</span>
</v-tooltip>

But it looks a bit weird. Also, only my second example allows setting modifiers on the click event.

@mtermoul
Copy link

mtermoul commented Feb 26, 2020

My 2 cents on all the complains about is that Vue came to save us from the boilerplate that we need to write in React, Angular.... So the selling point of Vue, Vuetify was Fast to learn and fast to write an app. However with this kind of syntax it's becoming very hard to understand and take longer to add a simple tooltip. Why not make a simple tooltip directive that 90% of use use all the time. And have the Tooltip delux component that allow you to have extra cheese, french fries, and sauce...

I think it's time for me to go on my own and write my own beautiful, simple, and powerful framework! I will call it vue-ez-fy

@jacekkarczmarczyk
Copy link
Member

#9610

For dialogs and menus we still need it

BTW i think in other places (lists?) we also use v-bind="attrs", so in docs it should mentioned as well

@LAxBANDA
Copy link

LAxBANDA commented Apr 6, 2020

how to export the click function to use on my v-model="dialog" and patterns components
<template v-slot:activator="{ on: { click }, value }"> <v-btn color="primary" dark class="mb-2" @click="click">Nuevo {{ value }} {{ dialog }} {{ title }}</v-btn> </template>

@Asinging
Copy link

Asinging commented Jul 8, 2020

sure but slot="activator" won't work anymore in vuetify 2.0

so what is replaces it cus i used in my project and seems not work

@bradlymathews
Copy link

bradlymathews commented Jul 25, 2020

<v-tooltip bottom>
  <template #activator="{ on }">
    <v-btn icon v-on="on" @click="openSettings">
      <v-icon>mdi-settings</v-icon>
    </v-btn>
  </template>

  <span>Settings</span>
</v-tooltip>

But it looks a bit weird. Also, only my second example allows setting modifiers on the click event.

I had to go through this entire thread to find the answer to my question: What is the correct syntax for getting a click event fired on a button that has a v-tooltip. Whew! And I still do not understand why I need any of that "on" stuff. This why I have so little hair left. Thanks to @pdcmoreira for figuring out that you just need to add a @ click.

@Dinuz
Copy link

Dinuz commented May 18, 2021

@pdcmoreira that's right. I did exactly that, but instead of using a single click I used the whole $listeners in a wrapper fashion way. it results in something like the following:

<template v-slot:activator="{ on }">
  <my-comp v-on="{...on, ...$listeners}" />
</template>

It makes sense if you think that are both objects:))
The issue raise when you forget that "on" is an object.

@pdcmoreira
Copy link

@Dinuz sure, but that's only if you want to pass all the listeners from parent to child.

@Dan88Hus
Copy link

this docs explanation can be short answer for all question about slots and its details :

@robinzimmermann
Copy link

I'm using typescript in vscode with vue-3 and vuetify next.

The sample code for a dialog on the vuetify site is:

<template>
  <div class="text-center">
    <v-dialog
      v-model="dialog"
      width="500"
    >
      <template v-slot:activator="{ on, attrs }">
        <v-btn
          color="red lighten-2"
          dark
          v-bind="attrs"
          v-on="on"
        >
          Click Me
        </v-btn>
      </template>

    ...
    </v-dialog>
  </div>
</template>

But I kept getting a ts compile error:

Property 'on' does not exist on type '{ isActive: boolean; props: Record<string, any>; }'.
Property 'attrs' does not exist on type '{ isActive: boolean; props: Record<string, any>; }'.

image

Thanks to some of the posts above, I was able to modify the code and get it working. The key line is to change:

<template v-slot:activator="{ on, attrs }">

to:

<template v-slot:activator="{ isActive: on, props: attrs }">

I'm just paying it forward in case this helps anyone else.

Thank you folks on this thread!

@lhuangjs

This comment was marked as off-topic.

@KaelWD
Copy link
Member

KaelWD commented May 3, 2022

@robinzimmermann
Copy link

Thanks @KaelWD!

And thank you for not also throwing in "RTFM!"

@danieldanielecki
Copy link

Is this still relevant? It seems to be all examples have been replaced with props instead, and v-on is no longer referred.

@KaelWD
Copy link
Member

KaelWD commented Apr 22, 2023

https://vuetifyjs.com/en/components/overlays/#activator-slot

@KaelWD KaelWD closed this as completed Apr 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests