When navigating into the same route you are currently at, the route query page
added by the before enter route guard is lost.
This is due to the fact that router link to
object does not contain query page
, and it does not go into before enter hook anymore, since it is already in the same route.
I figured out that you can add it in your router push or link button and you need to add this whenever you know the view contain query page
.
Example:
this.$router.push({ name: 'routeName', query: { page: 1 } });
Is there an elegant way to handle this in route guard?
Which hook should I use so that route query page
can be kept even user navigate into the same route?
Route
// Sample route
const routes = [
{
path: 'test',
name: 'Test',
component: TestPage,
beforeEnter: testPageGuard,
},
];
Route Guard
// Test Page Guard
testPageGuard: (to, from, next) => {
const { page = null } = to.query;
let finalNext;
if (!page) {
finalNext = {
...to,
query: {
...to.query,
page: 1,
},
};
}
if (finalNext) {
next(finalNext);
} else {
next();
}
}
View
// TestPage.vue
<template>
<!-- The problem can be reproduce when clicking this link
when you are already in route '/test' -->
<router-link :to="{ name: 'Test'}">
Test
</router-link>
</template>
<script>
export default {
name: 'Test',
};
</script>
// TestPage.vue
<template>
<!-- query page is added here -->
<router-link :to="{ name: 'Test', query: { page: 1 } }">
Test
</router-link>
</template>
<script>...</script>
I figured out that there are two more ways to do this.
beforeRouteUpdate triggers when query param changes even when in the same route.
Hence we can remove the beforeEnter guard and the extra page
query in the route link, and do query param page
adding at that particular page.
View
// TestPage.vue
<template>
<!-- The problem can be reproduce when clicking this link
when you are already in route '/test' -->
<router-link :to="{ name: 'Test'}">
Test
</router-link>
</template>
<script>
export default {
name: 'Test',
// Solution here
beforeRouteUpdate(to, from, next) {
if (!Object.prototype.hasOwnProperty.call(to.query, 'page')) {
next({
...to,
query: {
// This line is used to retain other query if there is any
...to.query,
page: 1,
},
});
} else {
next();
}
},
};
</script>
When query param changes even when in the same route, it actually go through beforeEach hook also.
Hence we can remove the beforeEnter guard and the extra page
query in the route link.
Add meta tag hasQueryParamPage
for that route and do query param page
adding in the global beforeEach hook.
This design has better reusability if you have other pages that require the query param page
.
Route
// Sample route
const routes = [
{
path: 'test',
name: 'Test',
component: TestPage,
// add meta tag
meta: { hasQueryParamPage: true },
},
];
Router
// router.js
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
...
});
// Solution here
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => (record.meta.hasQueryParamPage))) {
let updatedNext = null;
if (!Object.prototype.hasOwnProperty.call(to.query, 'page')) {
updatedNext = {
...to,
query: {
// This line is used to retain other query if there is any
...to.query,
page: 1,
},
};
}
if (updatedNext) {
next(updatedNext);
return;
}
}
next();
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With