Using Regex in vue router path - vue.js

In Vue router, I have a path /[can be anything in here]/products/shoes/nike
The first part is languageCode that can be anything or it may not be exist at all. I want to cover all of the possibilities. I tried
{
path: ':lang/products/shoes/nike',
meta: { allowGuest: true },
redirect: { name: 'shoes' },
},
Tried with path: '/:catchAll(.*)/products/shoes/nike' too but didn't work either.
I am still not able to catch routes starting with a languageCode. Is there a way I can do it with regex?

In order to make :lang optional in your route's path, you need to use ? modifier.
So, update your route object as follows:
{
path: '/:lang?/products/shoes/nike',
meta: { allowGuest: true },
redirect: { name: 'shoes' },
}
Refer official vue-router docs for detailed info- https://router.vuejs.org/guide/essentials/route-matching-syntax.html#optional-parameters

Related

Mapping multiple URLs to the same component with Vue Router

In my Vue 2.7.5 app (using Vue Router 3.5.4). I'm trying to map multiple URLs to the same component. Currently, I have a single route mapped to the component:
{
path: '/customer/:customerId',
component: CustomerOrders
}
My goal is to add an optional orderId parameter, such that if a URL like /customer/42/order/59 is accessed, then the same component is loaded, but the order with ID 59 is highlighted (the details of how the param is going to highlight the order are not important).
I tried changing the path to /customer/:customerId/orders/:orderId?, but this would no longer match any URLs of the form /customer/:customerId and would therefore be a breaking change.
My current solution is to use a child route:
{
path: '/customer/:customerId',
component: CustomerOrders,
children: [
{
path: 'order/:orderId',
component: CustomerOrders
}
]
}
This work as the CustomerOrders component is loaded by paths matching either /customer/:customerId or /customer/:customerId/order/:orderId, but it seems like a slightly convoluted approach and I'm not sure it's an appropriate use of child routes.
Is there a better solution?
The easiest way is to register the same component for both routes:
{
path: '/customer/:customerId',
name: 'CustomerOrders',
component: () => import( '../views/CustomerOrders.vue'),
},
{
path: '/customer/:customerId/order/:orderId',
name: 'CustomerOrders',
component: () => import( '../views/CustomerOrders.vue'),
},
An exact solution that you are looking for is parsing params manually:
{
path: '/customer/:param+',
name: 'CustomerOrders',
component: () => import( '../views/CustomerOrders.vue'),
props: router => {
const params = router.params;
const split = params.param.split('/');
params.customerId = split[0];
if (split.length > 2) {
params.orderId = split[2];
}
},
},
Here the :params+ ensures that a customerId and the rest of the route get caught. On the other hand, using :params* catches the /customer route without even a customerId.
CAUTION This approach also /customers/42/...everything...
The vue3 solution is solved here.
EDIT: the following approach cannot catch orderId
Using an alias improves reusability and reduces rendering time but comes with a price of capturing params-change in a watch handler.
{
path: '/customer/:customerId',
name: 'CustomerOrders',
alias: '/customer/:customerId/order/:orderId',
component: () => import( '../views/CustomerOrders.vue'),
},
In this case, your component doesn't get rebuilt by changing routes and also onMount or beforeCreate hooks don't get called either. To catch params-change add a proper watch:
export default {
name: 'CustomerOrders',
watch: {
'$route.params'() {
console.log('params changed. Extract params manually and reload');
},
},
};
This issue is addressed here.

Dynamically registered route is not working when it is just pushed

Hi i'm facing a problem where i want to add new route dynamically
My route structure will look something like this
I'm using "vue-router": "^3.5.3"
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, name:'User'
children: [
{
path: 'profile', component: Profile, name:'Profile'
children: [
{
path: 'about', component: About, name:'About'
children: [
{
path: 'details', component: Details, name: 'Details'
}
]
}
]
}
]
}
]
})
Now my intention is to add child route to Details
this is how my pseudo code looks like
findRouteWithName(routeObj,routeName)
{
// recursive find with any nested level
....
return foundRoute;
}
let routeObj = findRouteWithName(this.$router.options.routes,'Details');
routeObj.children.push(Route object{});
//this.$router.addRoutes([routeObj]) // this line creates problem as mentioned below in **problem:**
Note: if i'm doing like this https://stackoverflow.com/a/48833074/10054910 it is creating multiple nested routes in the url
Problem: page is becoming blank with direct push on children even route does not change in url. with this https://stackoverflow.com/a/48833074/10054910 approach route changes in url but append 2 times
Please help me thanks in advance !!

Recursive slugs in vue-router routes

I'm setting up a website which will contain groups, these groups can have sub-groups and these sub-groups can have sub-groups and so on...
Is this in any way possible?
Ofcourse making the path of a route like: /groups/:slug/:slug does not work since it contains duplicate params.
What I was thinking of was using the star pattern as child route, this child route will redirect the user back to the parent route with the slug and a sub-slug, then the next action will be to act on the sub-slug if it exists. But maybe someone has a better solution to this?
const groupRoute = {
path: `/groups/:slug`,
name: 'group',
component: Group,
children: [
{
path: '',
component: GroupsHome
},
{
path: '/subgroups',
component: SubGroups
},
{
path: '*',
beforeEnter(to, from, next) {
next({
name: 'group',
params: {
slug: to.params.slug,
subSlug: to.params.pathMatch
}
})
}
},
]
}
Here is a basic example:
Nested navigation with similar structure for nested objects. The trick here is to use a different param name for inner routes.

Vue ,listen to route param change but not child route change?

I have the following structure in vue.js ,using vue-router.
routes: [
{
path: '/domains',
component: ListOfDomains
},
{
path: '/domain/:domainName',
component: Domain,
children: [{
// Photos Tab content will be rendered inside domain's <router-view>
// when /domain/:id/photos is matched
path: 'posts',
name: 'posts',
component: PostsTabContent
},
{
path: 'photos',
name: 'photos',
component:PhotosTabContent
}
]
}
]
In my Domain component I use a watcher to fetch domain related data from server such as:
"$route": function(to, from) {
console.log("watcher triggered");
//do update only if domain has changed
//do something , ajax request , update store etc
}
This seems to work fine, but my problem is that I only want to do my updates if the url changes from, say, domain/domain23/posts to domain/domain45/posts and not when it changes from domain/domain23/posts to domain/domain23/photos.
How can I watch only that level in the route for changes?

Unable to understand how vue-router query params work

I am building an app with the following route settings.
export default new Router({
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/home',
name: 'Dashboard',
component: Dashboard,
beforeEnter(to, from, next) {
if (!store.getters.isLoggedIn) {
next('/login');
} else {
next();
}
}
},
{
path: '/',
redirect: '/home'
}
]
});
I also set query parameters based on some select boxes I have by using $router.push say as follows.
this.$router.replace({
query: {
scope: this.$store.getters.filterScope
}
});
Problems I have
Reloading the page removes the query params from the URL.
Updating one query parameter removes the other one I had. Example - updating scope using the above method removes the dateRange parameter I already had.
I am using Vuex too so is there any way I can manage these query params using the store?
If you store your parameters in vuex and you don't use vuex-persistedstate, when you refresh the page state will be removed.
So, my suggestion for you:
your-awesome-site.com/dashboard?first=hello&second=hi
In your Dashboard component, you can do like this
mounted () {
console.log(this.$route.params)
// Update vuex state filterScope
}
So you will retrieve your parameters from url and save it in vuex.
Also you can solve your second issue using this.$route.params