It would be great if we will be able to at least detect when our users click the same router-link again.
Let me explain:
Let's say I have an app with fixed navbar on top and a user have navigated to a long page (let it be /news) and at one moment after long scrolling (let the page have infinite scroll) the user decides to click the same link /news again (from the navbar), obviously to go up (or to refresh the page, who knows), but the problem is that nothing will happen (it feels like the link is dead), and as far as I know there is no way to capture multiple clicks on the same route-link without using some hacky workarounds.
The problem can be solved for example by adding a timestamp to query string so every time user clicks the same link the navigation will happen again, but it feels so wrong, because the only thing basically what should happen is the scroll to an anchor or scroll to the top.
So, it would be great to have an option to detect when users click the same router-link multiple times without hacky workarounds, or at least an option to scroll to the top on secondary click.
If there is an elegant option to do it now, please tell me, because I didn't find such feature in the documentation.
Hey, you can actually add an event listener like @click.native: http://jsfiddle.net/posva/5ra5asny/
This will be triggered every time 馃檪
@posva hmm seems he's asking how to only trigger a function when you click on the same route, in your example when I click home on foo page the event will also be fired
If there is an elegant option to do it now, please tell me, because I didn't find such feature in the documentation.
beforeRoueUpdate() should work nicely, no? if to and from have the same .path, that's a "refresh" click.
@egoist Yes, you're right. In that case the user can check that the route is the same in the click event. Maybe we can fire a new event when the user clicks on the router-link while it's the current route. But currently, you can achieve that on userland already
edit: the beforeRouteUpdate wasn't a thing back there 馃槅 . But it shouldn't fire if the route didn't change eg: a rout with no params
@posva I've tried to check if the route is the same in the click event, but it seems that the event is fired after navigation, because when I tried to compare current route with the route from link they were same all the time.
P.S: For now, I've solved my issue from the first post with a wrapper component for <router-link/> which also fires an event on each navigation so I can do my scroll :)
@LinusBorg
beforeRoueUpdate() should work nicely, no? if to and from have the same .path, that's a "refresh" click.
seems no, as per doc: // called when the route that renders this component has changed
Oh, nevermind ^^
So maybe reopen this?
Why does it have to be the second time? Why not simply scroll to the top on every click?
Yes, the fact that the click triggers after the navigation mean that you have to manually handle everything or use a query like ?t=${Date.now()} like http://jsfiddle.net/posva/2c2dfmqb/
So, I think we should can emit some kind of custom event like activate when a router-link is clicked while the current route is already the one we have
@fnlctrl Imaging you're reading a news feed, and click on one of the news to get more details, then you want to go back, but instead of doing back, you click on the news button because it's there, we may want to scroll to where the user was last time he was on the news feeds. I'll personally hit Back, but some people forget about this really often. Also, in a PWA on an iPhone, you may not have a back button
I think we're complicating the problem here...
What's wrong with clicking the link always resulting in scrolling to the top? If the user clicks the link from another route, it's fine since he would expect it as new contents are loaded. If you want the click handler to be called on the second (or more) click, why not for the first click?
<router-link to='/foo' @click.native="toTop"/>
methods: {
toTop: {window.scrollTo(0,0)}
}
@posva That's not what OP originally asked for. From my perspective, rendering a dedicated a back button would be most appropriate for this use case.
@posva That's not what OP originally asked for. From my perspective, rendering a dedicated a back button would be most appropriate for this use case
I didn't express myself correctly. I also think that way 馃槅
@fnlctrl Yes, you're right, and your example shows that I was trying to acheive, but, for now, you will have to repeat that @click.native="toTop" almost on every <router-link/>, and if multiple components also have links, you will have to repeat the method too, or to extract it to a dedicated file and to include it in methods list every time.
As I wrote in another comment, I've solved this with a wrapper component for <router-link/> which also adds a @click.native with the scroll method, but having just an event would be better, as the click event is fired after navigation so we can not detect if route was changed or not, if for some reason we may need this.
P.S: Also, the sensation of 'dead' links is not user firendly, because when user clicks a link (even the second time), he/she expects at least something to happen (scroll, in our case).
Well, I think duplicating @click.native="toTop" is still better than a complicated mechanism with vue-router.
To reduce duplicated code there are some easy ways, e.g.
<div class="nav-bar" @click="toTop">
<router-link ....../>
<router-link ....../>
<router-link ....../>
...
</div>
toTop to Vue's prototypeVue.prototype.$scrollToTop = () => window.scrollTo(0,0)
And it can be used everywhere including templates.
<router-link @click.native="$scrollToTop">
What if I don't really want to scrolling to the top when switching to a new route 馃槀 I want to handle that in the mounted function of that route, the content of new route might be loaded asynchronously and if we scroll to top before the content loaded and then scroll to top again in that route, it will just look weird. Especially scroll with animation.
What if I don't really want to scrolling to the top when switching to a new route
...I guess you can just don't bind a click event?
or something like
<div class="nav-bar" @click="toTop">
<router-link @click.native.stop ....../> // now clicking this won't scroll to the top
<router-link ....../>
<router-link ....../>
...
</div>
I want to handle that in the mounted function of that route, the content of new route might be loaded asynchronously and if we scroll to top before the content loaded, it will just look weird. Especially scroll with animation.
Then it's not suitable to be handled by vue-router anyway, as it's supposed to be handled by userland.
@fnlctrl In that case, to my mind, a wrapper component seems to look better, and we can use it like <scroll-link/> every time we need the scroll:
<template lang="pug">
router-link(
:to="to",
:tag="tag",
:exact="exact",
:append="append",
:replace="replace",
:activeClass="activeClass",
:event="event",
@click.native="scroll"
): slot
</template>
<script>
export default {
props: [ /* .. */ ],
methods: {
scroll() {
window.scrollTo(0,0);
}
}
}
</script>
Yeah, it looks nice indeed. Closing as the issue is now resolved in userland ;)
I am having the same problem while trying to implement a menu which comes back to home when clicking on the active link. And like it was mentioned I cannot compare the link's to property with the current route's path because the route changes before.
When searching the documentation, I was expecting a callback like router.beforeEach which happens on any router link before router.beforeEach. Such a callback most likely exist and is not exposed because there is a click event which decides if the route needs to change or not.
See #974
Most helpful comment
Hey, you can actually add an event listener like
@click.native: http://jsfiddle.net/posva/5ra5asny/This will be triggered every time 馃檪