How do I reload the web app when current route link is clicked again? - vue.js

Please take a look at the fiddle
https://jsfiddle.net/L3px7okf/
I want to reload the app when the same route (for example /foo) which you are currently on is clicked again because I need to reset the page state (yes, the correct way would be, actually, to reset the state, but the application code is a bit tricky thus I need a quick solution).
But I don't want to reload the app when I'm clicking /foo being on route /bar.
The problem is that VueRouter does nothing when the same link is clicked. Global (like beforeEach) and in-component (like beforeRouterEnter/beforeRouteLeave) hooks are not called. #onclick.native event handling doesn't help because when the handler is executed the route is already updated.

I found this...https://stackoverflow.com/a/51170320/10039548
<router-view :key="$route.fullPath"></router-view>
Seems like they talk a bit about this issue here

this.$router.go()
Can refresh the page on click..

Try using <a href="your route here"> I've used this and it's working just fine.

Related

Disable SPA mode for all links In Nuxt

When an update for my app is released, I would like all users to access the new version asap.
I'm looking for a way to disable all nuxt-links normal internal routing and reload the page to the new url when an update is detected.
Is it possible to change this globally? (without adding code to every nuxt-link):
Remove the nuxt-link bahavior from nuxt links that are already <a href links?
Update the nuxt-link behavior to do a location.href = instead of the internal navigation (for links on non-a elements or router.push)
In this case you could build a wrapper component that you will use instead of <NuxtLink> which contains the wanted functionality and passes props and events to the <NuxtLink> component otherwise.

Nuxt-link delay transition to new page?

This is a follow up to #1458. I'm looking for some direction on how Nuxt expects this to be handled.
I have a menu. When I click on a nuxt-link in the menu, I want to have time to close the menu before the page transition happens. The thing is, I only want that to happen when you click on the nuxt-link in the menu, not every time I go to a certain route (as the previous issue described using a middlewear on the route).
So there are a few different ways to do this, and I'm curious what the "Nuxt" way is?
The way we currently do this, disable the nuxt-link and capture the click, then do a router.push().
<nuxt-link :to="path" event="disabled" #click.native="delayLoad"/>
// Methods
delayLoad(event) {
this.$store.commit("CLOSE_MENU")
setTimeout(()=>{
this.$router.push(event.target.pathname)
}, 2000)
}
Is this a good idea? I just always have an aversion to hijacking nuxt-link and browser navigation like this. It seems janky.
The other ideas we played with were using a query param on the nuxt-link, and then using that in a middlewear to delay the page transition. That seemed worse to me, because now my URL's have a query param in them that is used for an animation, seems like that is abusing query params. This also triggers the page loading progress bar, which isn't really the intent, it's to have a sequenced animation happen, then page load.
It seems to me that perhaps nuxt-link should have a delay prop, or perhaps the page transition config should allow for a delay (like it does with duration)?
I wanted to do this as well and came up with the following solution. Using the new slots api you can more elegantly customise the nuxt-link behaviour:
<nuxt-link v-slot="{ route, href }" :to="path" custom>
<a :href="href" #click.prevent="$emit('navigate', route)">
<slot></slot>
</a>
</nuxt-link>
This will make the link emit a navigate event with the route as a param. You then listen for this event wherever you include your menu component, like this:
<template>
<transition
name="fade"
#after-leave="maybeNavigate"
>
<MainMenu
v-if="menuIsVisible"
#navigate="navigate"
/>
</transition>
</template>
<script>
export default {
data: () => ({
menuIsVisible: false,
navigateToOnMainMenuClose: null,
}),
methods: {
navigate(route) {
this.navigateToOnMainMenuClose = route
this.menuIsVisible = false
},
maybeNavigate() {
if (this.navigateToOnMainMenuClose) {
this.$router.push(this.navigateToOnMainMenuClose)
this.navigateToOnMainMenuClose = null
}
},
},
}
</script>
Whenever you click a nav link in the menu, the route will be stored and the menu will close. After the menu out animation has finished, maybeNavigate() will push the stored route, if there is one. This removes the need for a setTimeout and if you manage to click multiple links in quick succession only the last one will be stored and navigated to.
Since nuxt-link is essentially a wrapped version of vue's router-link, if you look at the documentation for that there is an event property that accepts string or string[], looking at it's source code here: https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L86
you can see it will register a listener for disabled in this instance. It may make more sense to pass an empty array so that no event listeners are registered, but that's at the cost of readability.
Otherwise, #click.native is the suggested way to handle custom click handlers for router-link (see: https://github.com/vuejs/vue-router/issues/800#issuecomment-254623582).
The only other concerns I can think of are what happens if you click 2 different links in rapid succession and what happens if you click more than once. May just want to add a variable to track if a link has been clicked to prevent firing setTimeout multiple times, which could navigate you from page A to B and then to C as all timeouts will fire if not canceled. Or maybe you want to only navigate to the 'last' link clicked, so if another link is clicked, you would cancel the earlier setTimeout. This is realistically an edge case that probably won't be an issue, but worth exploring.
Otherwise, IMO, looks good to me. This seems like the simplest way to implement this without having to create a custom component / plugin. I'm no expert, but is likely how I would implement this functionality as well. It would be nice to see a delay option though since I can see myself using that functionality as well with vuetify.
Another potential method would be to do your store commit in beforeTransition: https://nuxtjs.org/api/configuration-transition/
Though I'm not sure that there is access to the store there, so you might have to write a custom plugin for that as well. Again, seems more complicated than it's worth for a simple delayed animation. Simple, working code is sometimes the best solution, even if it's not the most extensible option.
See also: How can I transition between two nuxt pages, while first waiting on a child component transition/animation to finish?
for another way of handling this.

NUXT VUE Transition in component when leaving page

I got the following setup in nuxt
page/blog/index.vue
components/topheader.vue
I would like to have transition effect when you leave a page and enter the page in the component topheader. The title should fadein/fadeout. This because now the title is replaced very abrupt without a transition effect.
The problem is when you go to a new page/route the animation has no time to go ahead. So I have some success with stopping the the router with beforeRouteLeave then pass a prop "showTitle" to the component setting it to false. Set a timeout on the next() in beforeLeave ...
But this feels quite wrong and bad practice
I Looked in to setting in nuxt.conf transition. But this is for the a page transition and has only an effect on the complete page. It seems I can't target something in a component only there. My feeling is I should be able to do this with some setting there. However I'm missing something.
For appearing the transition I can use ...
Now my question. How to target something in a component of a page to create a transition on leaving the page. Ideal the loading is already started so the transition takes about the time between the page loads.
thx in advance
You can wrap your component with the <transition name="yourTransitionName"></transition> tag.
In CSS:
.yourTransitionName-leave-active {
/* your code */
}

VueJs won't reload Javascript on browser back button

In a login page, I have a Google reCAPTCHA. It works as intended, but if I navigate to another page, and then return via the browser's back button, or by typing the URL in the browser, everything works except said reCAPTCHA. For it to work again, I need to reload the page. I get the same results when using Materialize with Vue. The components won't "reset" when back on the page.
Tried to use keep-alive (even if that sounds wrong), tried various Vue lifecycle hooks (created, beforeMount, mounted), tried to keep the code in a function which I then called in the lifecycle hooks. Nothing seems to work. I searched Google and even here, but maybe I'm using the wrong search terms, as I couldn't find a solution to the problem.
Can someone shed light on the problem? I can try to provide code if needed.
It's hard to give 100% sure answer when there is no reproduction supplied but this is what might work:
Try adding key parameter to router-view:
<router-view :key="$route.path" />
Or even on a component you want to be re-rendered:
<component-with-recaptcha :key="$route.fullPath"></component-with-recaptcha>

Clicking on active router-link

In my Vue 2 app, I have a menu bar whose menu items use router-link. One of these menu items is 'Customers', which takes the user to a customer editor. Now, if the user clicks on this same 'Customers' menu item while they're in the customer editor, nothing happens. I presume this is because of this behaviour mentioned in the docs: "In HTML5 history mode, router-link will intercept the click event so that the browser doesn't try to reload the page."
Now, that's perfectly understandable and for the majority of the time it would be the behaviour I want. But actually here I want the component to be reloaded, to go back to a clean slate. Or perhaps more accurately, for some event to occur which I can handle within the customer editor to set things how I want them to be. I assumed this would be the case, in fact, but when I set up a watch, thus
watch: {
'$route' (to, from) {
console.log("Route changed");
}
},
I don't see anything logged to the console. It may be that some event is occurring which I'm not handling and that Vue is simply reusing the component. But how can I stop it from doing so?
According to this issue, you can add a #click.native binding to the current router-link and reinitialize your component data in there.
But a quick and dirty solution would be to append a unique parameter to your route, like a date. Check this fiddle
The intended method of accomplishing this seems to be to implement a beforeRouteUpdate function to reset the properties of the route component. See this issue on vue-router's GitHub: Routing the same component, the component is not reload, but be reused? #1490.
This is expected behaviour, Vue re-uses components where possible.
You can use the beforeRouteUpdate hook to react to a route switch that
uses the same component.