Enclosing a router-link tag in a button in vuejs

127,486

Solution 1

You can use tag prop.

<router-link to="/foo" tag="button">foo</router-link>

Please use v-slot if you use 3.0+ (thanks to Romain and Jeff)

Solution 2

While the answers on here are all good, none seem to be the simplest solution. After some quick research, it seems that the real easiest way to make a button use vue-router is with the router.push call. This can be used within a .vue template like this:

<button @click="$router.push('about')">Click to Navigate</button>

Super simple and clean. I hope someone else finds this useful!

Source: https://router.vuejs.org/guide/essentials/navigation.html

Solution 3

@choasia's answer is correct.

Alternatively, you could wrap a button tag in a router-link tag like so:

<router-link :to="{name: 'myRoute'}">
  <button id="myButton" class="foo bar">Go!</button>
</router-link>

This is not so clean because your button will be inside a link element (<a>). However, the advantage is that you have a full control on your button, which may be necessary if you work with a front-end framework like Bootstrap.

I have never used this technique on buttons, to be honest. But I did this on divs quite often...

Solution 4

Official Answer as of 2022

Use the slots api Documentation Here

Example using the slots api

<router-link
  to="/about"
  v-slot="{href, route, navigate}"
  >
    <button :href="href" @click="navigate" class='whatever-you-want'>
      {{ route.name }}
    </button>
</router-link>

If you think this is unintuitive/verbose, please complain over here

Why are the other answers problematic?

  • @choasia's answer (using the tag prop) is deprecated and doesn't allow for props to be passed to the component

  • @Badacadabra's answer causes problems with CSS especially if the button is from a library (ex: adding a margin, or positioning)

Solution 5

Thanks to Wes Winder's answer, and extending it to include route params:

<button @click="$router.push({name: 'about-something', params: { id: 'abc123' },})">Click to Navigate</button>

And reiterating the source which Wes provided: https://router.vuejs.org/guide/essentials/navigation.html

Share:
127,486
Kushagra Agarwal
Author by

Kushagra Agarwal

Updated on July 08, 2022

Comments

  • Kushagra Agarwal
    Kushagra Agarwal almost 2 years

    Can I wrap or enclose a router-link tag in a button tag?

    When I press the button, I want it to route me to the desired page.

  • vir us
    vir us about 5 years
    Additionally one can specify tag="span" inside <router-link> so it doesn't apply <a> styles which gives even better control on the looks: <router-link to="/foo" tag="span"> <Button> Button Text </Button> </router-link>
  • Joe Who
    Joe Who about 5 years
    Yes thank you! This was the simplest, and worked perfectly. And I could style my button however I chose. If you need to use params, you can also do something like this: <button @click="$router.push({name: 'about', params: { id: $route.params.id },})">Click to Navigate</button>
  • andcl
    andcl almost 5 years
    What if that button accepts some props? How to pass them out?
  • Tozz
    Tozz almost 5 years
    But the words in button (e.g. "Go!" in your example) will have the blue underline, which is not beautiful...
  • Ciabaros
    Ciabaros over 4 years
    Even with frameworks like Bootstrap, this is hardly ever necessary, because you can include standard attributes like class right in the router-link tag, and these will be applied to the rendered element, even a button, when you use tag="button": <router-link tag="button" class="btn btn-primary" to="..."></router-link>
  • Jeff Hykin
    Jeff Hykin over 4 years
    @andcl I had the same question, I posted the answer below, which was told to me by the Vue-Router team on GitHub here: github.com/vuejs/vue-router/issues/3003
  • Akin Hwan
    Akin Hwan over 4 years
    i tried to upvote this almost a year after i already did! akkk thanks again
  • sshow
    sshow over 4 years
    If you're not on version >= 3.1.0, the item in the slot will silently be ignored without any errors show. Link to docs: router.vuejs.org/api/#v-slot-api-3-1-0
  • The Fool
    The Fool over 3 years
    i cannot download 3.1.0 it says the latest is 3.0.0 rc
  • Anuga
    Anuga over 3 years
    It's not Vue 3.1.0, it's vue-router 3.1.0.
  • Jeff Hykin
    Jeff Hykin over 3 years
    Thanks @Anuga, fixed it 👍 And thanks @ sshow, documentation is linked now.
  • Tomas Chabada
    Tomas Chabada almost 3 years
    The best answer for me
  • Nikita
    Nikita over 2 years
    Note that this answer this won't allow to use browser supported features such as press Ctrl+Click to open link in new tab or preview of link in bottom-left corner of browser window.
  • Steven Spungin
    Steven Spungin over 2 years
    Use the modern slot API <template #default="{href,route,navigate}">
  • Jeff Hykin
    Jeff Hykin over 2 years
    @Steven could you link the documentation on that? I haven't seen it yet but that looks interesting
  • Steven Spungin
    Steven Spungin over 2 years
  • Jeff Hykin
    Jeff Hykin over 2 years
    Hmm I'm not totally sure how that would apply to the example. Are you saying to replace v-slot="{href, route, navigate}" with #default="{href, route, navigate}"? It looks like v-slots is shorter, still valid, and backwards compatible with Vue 2
  • Charles HETIER
    Charles HETIER about 2 years
    The :href should not be bound on the button. The targeted url is already held by the property to="xxx" of the <router-link>
  • Romain Vincent
    Romain Vincent about 2 years
    But "tag" is no longer supported by vue-router. See official migration note. And anyway, I don't recall exactly, but I doubt it handled additional link features and accessibility.