vue-function-api currently lacks support for vue-router in-component navigation guards (beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave). Any plans to implement them in the near future, or it's out of scope of this project?
I don't think beforeRouteEnter is possible as it's executed before a view component is mounted. Once the setup function is called, the navigation has already been confirmed
How are you working around this? Watchers on props?
@timshannon for the beforeRouteEnter guard, I suppose a possible workaround is using beforeEnter guard (defined directly in router, not in component) instead. For the other guards, one needs to deliver proper hooks like onBeforeRouteUpdate and onBeforeRouteLeave for Composition API.
What I'm doing in the moment is just not using Compostion API at all for components that need navigation guards.
The beforeRouteEnter is working for me. Looks like it was added in v0.3.2.
A couple of notes that I found when using beforeRouteEnter:
any data that you pass back to the component like
next(vm => {
vm.foo = 'bar';
});
Won't be available in the setup() method initially. It will work in your template as long as you pass it through the return{}, but if you need to access the data in the setup method you will need to do 2 things.
context.root.$nextTick(() => { console.log(foo);});Navigation guards only seem to work when accessing the vm in the next() function.
However, I can't get them to work otherwise.
example:
export default createComponent({
beforeRouteLeave() {
doFunction();
}
setup() {
function doFunction() {
// Do Stuff
}
return {
doFunction
};
}
}
How can I call a function from beforeRouteLeave that is in the setup() function without using the next(vm => {});
In the Options API you would use this.doFunction(); So what is the equivalent in the new Composition API?
Well, I found a work around:
beforeRouteLeave(to: any, from: any, next: any) {
from.matched[0].instances.default.doFunction();
next();
},
Although, this doesn't really seem like the ideal solution.
If anyone knows a better way then let me know.
PS. You need to make sure that the function is in the return of the setup() function.
Any progress about this kind of support in @vue/composition-api? Maybe supporting some kind of onBeforeRouteUpdate() / onBeforeRouteLeave() hooks inside setup()?
Well, now I need to use beforeRouteUpdate and running next() seems to re-run setup(). Which in turn overwrites any data I set using "from.matched[0].instances.default". I tried using a setTimeout or NextTick, but the data does not get updated. So it seems that beforeRouteEnter works has you have access to the callback and beforeRouteLeave works sort of with "from.matched[0].instances.default". But beforeRouteUpdate doesn't seem to work as you lose context after next() runs.
The issue I am facing is switching routes within path/:id
so switching from path/12 to path/13 doesn't allow me to swap out the item.
Any new on this? I've got a similar problem. I want to call a function from beforeRouteLeave(). The function is defined inside of setup() in order to have access to the refs that are defined there.
So my code looks a bit like this (abbreviated):
setup() {
const titleEditor = ref(null);
const textEditor = ref(null);
function flushEditors() {
if (textEditor.value) {
textEditor.value.flushEvents();
}
if (titleEditor.value) {
titleEditor.value.flushEvents();
}
}
return { flushEditors };
},
beforeRouteLeave(_to: Route, _from: Route, next: NavigationGuardNext) {
this.flushEditors();
next();
}
This works, but TypeScript is throwing errors because there is no typing for flushEditors() on this. Also, I have a feeling that this won't work in Vue 3. Any ideas or hints?
I don't know if that's still relevant to anyone but I ended up making my own (very simple) composable function:
import Vue from 'vue'
import { getCurrentInstance } from '@vue/composition-api'
import { NavigationGuard } from 'vue-router'
import { ComponentOptions } from 'vue/types/umd'
export function onHook(
name: keyof ComponentOptions<Vue>,
callback: (...args: any) => void
) {
const vm = getCurrentInstance()
const merge = Vue.config.optionMergeStrategies[name]
if (vm && merge) {
const prototype = Object.getPrototypeOf(vm.$options)
prototype[name] = merge(vm.$options[name], callback)
}
}
export function onBeforeRouteUpdate(callback: NavigationGuard<Vue>) {
return onHook('beforeRouteUpdate', callback)
}
export function onBeforeRouteLeave(callback: NavigationGuard<Vue>) {
return onHook('beforeRouteLeave', callback)
}
You can then simply use it as a regular "composable" hook:
import { onBeforeRouteUpdate } from '@/composables/router'
export default {
setup() {
onBeforeRouteUpdate((to, from, next) => {
// your logic
next()
})
}
}
The composable function of @yassipad doesn't work in Vue3 because of Vue.config.optionMergeStrategies.
Is there anyone that could point me to the right direction to make this work in Vue3?
Also the beforeRouteLeave isn't triggered in Vue3. Maybe it's removed as suspected by @sseeland.
@melenaos that composition function is a workaround for Vue 2. Vue Router Next should support this natively https://next.router.vuejs.org/guide/advanced/composition-api.html#navigation-guards in Vue 3
Thanks! I missed that because I was looking at the previous Router documentation.
From: Jose G. Alfonso notifications@github.com
Sent: Πέμπτη, 29 Οκτωβρίου 2020 11:47 μμ
To: vuejs/composition-api composition-api@noreply.github.com
Cc: melenaos menelaosvergis@gmail.com; Mention mention@noreply.github.com
Subject: Re: [vuejs/composition-api] Vue-Router navigation guards? (#49)
@melenaos https://github.com/melenaos that composition function is a workaround for Vue 2. Vue Router Next should support this natively https://next.router.vuejs.org/guide/advanced/composition-api.html#navigation-guards
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/vuejs/composition-api/issues/49#issuecomment-719043239 , or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXJ2CGN62UL6OCXZ5DP7BTSNHPGRANCNFSM4IJNF3PA . https://github.com/notifications/beacon/ABXJ2CEGTZ7TJZBAG52XIH3SNHPGRA5CNFSM4IJNF3PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOFLN3VJY.gif
@yassipad hello, thank you for the solution. Unfortunately with vue2 composition api it does not work for me
export const Navbar = defineComponent({
setup() {
onBeforeRouteUpdate((to, from, next) => {
console.log([to, from]);
next();
});
nothing happens when I switch route. maybe because we use children routes?
the main route always remains / and only children routes will change on navigation.
what would be a solution in this case?
this is what I ended up with
export const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
const observableRoute: {route: Route | {}} = {
route: {}
};
const routeData = Vue.observable(observableRoute);
router.afterEach(route => {
routeData.route = route;
});
export function useCurrentRoute() {
return computed(() => routeData.route as Route);
}
and usage
setup() {
const currentRoute = useCurrentRoute();
@seyfer Hi, I just made a very quick test using Vue2+VueComposition API and it seems to be working fine (https://codepen.io/yassipad/pen/gOMjzOe). What do you mean when you say you're using children routes?
@melenaos The hooks are indeed already available in VueRouter Next. Also, Vue.config.optionMergeStrategies is still accessible but it is now context specific: vm.root.appContext.config.optionMergeStrategies.
Most helpful comment
Any progress about this kind of support in @vue/composition-api? Maybe supporting some kind of
onBeforeRouteUpdate()/onBeforeRouteLeave()hooks insidesetup()?