Vue3 Redirect with dynamic property - javascript

I have this configuration in my router.ts:
{
path: "/admin/operations/job-allocation/:id",
name: "JobAllocation",
component: () =>
import(
"#/views/admin/operations/job-allocation/index.vue"
),
children: [
{
path: "",
redirect:
"/admin/operations/job-allocation/:id/operatives",
},
{
path: "/admin/operations/job-allocation/:id/operatives",
name: "JobAllocationOperatives",
alias: "Operatives",
component: () =>
import("#/views/common/Operatives.vue"),
},
]
}
When I visit the path: /admin/operations/job-allocation/1 I want to go to /admin/operations/job-allocation/1/operatives.
But in this setup it goes to /admin/operations/job-allocation/:id/operatives (the :id as a literal string of ':id' instead of being replaced by the number 1.
I'm hoping to use the router to do this, instead of using a 'mounted' hook to do the redirect at the JobAllocation component.
Is this even possible? I did not find this senario in the official Vue3 Router docs.

Use the object form of redirect to specify the route by name, so that the parameters are automatically passed along:
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: HelloWorld
},
{
path: '/admin/operations/job-allocation/:id',
name: 'JobAllocation',
props: true,
component: () => import('#/views/admin/operations/job-allocation/index.vue'),
children: [
{
path: '',
redirect: {
name: 'JobAllocationOperatives', 👈
},
},
{
path: '/admin/operations/job-allocation/:id/operatives',
name: 'JobAllocationOperatives',
alias: 'Operatives',
component: () => import('#/views/common/Operatives.vue')
}
]
}
]
})
demo

Related

vue-router 4 '/:pathMatch(.*)*' not working?

hello guys I want to ask about vue-router.
when I use vue 2 if there is a page that doesn't match, I use path: '*' to go to my page404 but in vue 3 it's been replaced with '/:pathMatch(.)' after i tried it the warning in console disappeared but i just got a blank page and it doesn't point to my page404. did i miss something? I'm newbie with vue 3
here is the version I'm using:
vue: ^3.0.0
vue-router: ^4.0.0-0
and this is my index.js
import { createRouter, createWebHistory, RouterView } from 'vue-router'
const routes = [
{
path: '/',
redirect: '/login',
component: RouterView,
children: [{
path: '/login',
component: () => import('#/views/login/Login.vue'),
}]
},
{
path: '/:pathMatch(.*)*',
component: () => import('#/views/page404/Page404.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
You can try to write it like this
{
path: "/:pathMatch(.*)*",
redirect: "/404"
},
{
path: "/404",
name: "404",
component: () => import("#/views/page404/Page404.vue")
}

Vue nested route

I have the following route from my vue app. Where I've created a nested route.
With the following code I'm not able to see the contents of my children route /admin/create-post
When I vist the route /admin/create-post the content of it's parent route /admin is shown
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home')
},
{
path: '/admin', component: () => import('../views/auth/Dashboard'),
name: 'Dashboard',
children: [
{
path: 'create-post',
component: () => import('../views/auth/PostEdit'),
name: 'Create Post'
},
]
},
{
path: '*',
component: () => import('../views/error/404')
}
]
Working demo: Code sandbox

Problem with programmatic navigation in vue.js

I'm developing a Vue.js application and there is something that I can't figure out about programmatic navigation.
As you can see below in my index.js file I have a tree structured routes in my client, some of this route need to be protected.
The routes that must be protected are the ones that are child of 'dashboard'.
When the App is loaded, if the user try to navigate one of those protected routes, the client send a request to the server, asking if the token that he possess allow him to access those protected routes, if the answer is yes then the user can freely navigate, otherwise I want to redirect him to the login page.
The problem arise here, how you can see from the 'App.vue' if the request checkSession fail (meaning no valid token has been provided) the error will be catched and this.$router.push('/login') is executed, but without success, in fact the url does not change at all.
I tried to print the router object and I have noticed that the route that I'm trying to push appear under history.pending properties of the cited object.
Another weird thing that I've noticed: if I delete the redirect in the routes path (the very last one) declared in the 'index.js' file and I load the App through an url that does not belong to one of the declared routes, for example '/wrong/path', and the user does not provide a valid token then $router.push('/login') works fine.
index.js
...
const routes = [{
path: '/login',
name: 'login',
component: LoginComponent
},
{
path: '/',
name: 'dashboard',
redirect : '/dipendenti/aggiungi',
component: DashboardComponent,
children: [
{ path: 'dipendenti', component: MiddleWareComponent, children:[
{ path: 'aggiungi', component: AddWorkerComponent },
{ path: 'elimina', component: DeleteWorkerComponent },
{ path: 'modifica', component: ModifyWorkerComponent }
]},
{ path: 'clienti', component: MiddleWareComponent, children:[
{ path: 'aggiungi', component: AddClientComponent },
{ path: 'modifica', component: ModifyClientComponent }
]},
{ path: 'team', component: MiddleWareComponent, children:[
{ path: 'aggiungi', component: AddTeamComponent },
{ path: 'elimina', component: DeleteTeamComponent },
{ path: 'modifica', component: ModifyTeamComponent }
]},
{ path: 'lavori', component: MiddleWareComponent, children:[
{ path: 'visualizza', component: ViewWorkComponent },
{ path: 'aggiungi', component: AddWorkComponent },
{ path: 'elimina', component: DeleteWorkComponent },
{ path: 'modifica', component: ModifyWorkComponent }
]},
{ path: 'account', component: MiddleWareComponent, children:[
{ path: 'modifica', component: ModifyAccountComponent }
]}
]
},
{ path: '/logout', component: LogoutComponent },
{ path: '/password-forgot', component: PasswordForgotComponent },
{ path: '/password-reset/:token/:api', component: PasswordResetComponent },
{ path: '/*', redirect : '/' }
];
const router = new VueRouter({
routes: routes,
base: __dirname,
base: process.env.BASE_URL,
mode: 'history'
});
...
App.vue
<script>
import Vue from 'vue';
import axios from 'axios';
Vue.prototype.$https = axios.create({
baseURL: 'http://localhost:5000',
withCredentials: true,
crossdomain: true
});
Vue.prototype.$checkSession = function() {
if (window.location.pathname != '/login' && window.location.pathname != '/password-forgot' && window.location.pathname.split('/')[1] != 'password-reset') {
var authToken = localStorage.authToken? localStorage.authToken:sessionStorage.authToken;
this.$https.defaults.headers.common['x-csrf-token'] = authToken;
this.$https.get('api/web/user/session').then(response => {
if(window.location.pathname == '/'){
this.$router.push('/dipendenti/aggiungi');
}
}).catch(e => {
console.log(this.$router.app);
this.$router.push('/login');
})
}
}
...
export default {
name: 'app',
created: function() {
this.$checkSession();
}
};
</script>
The desired behavior would be the redirect to the login page.

Angular Routes not mapping properly for lazy loading

So I have an app with multiple modules that has routes properly put in place, and each module has it's own routes. Everything works fine, until I try to implement lazy loading.
Previous State:
example module
export const EXAMPLE_ROUTES: Routes = [
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{
path: 'edit/sdg-info', component: SdgInfoComponent
}
]}
];
I import this EXAMPLE_ROUTES in example module
Now I have root level routing as
const APP_ROUTES: Routes = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', component: ExampleComponent, children: [...EXAMPLE_ROUTES], canActivate: [AuthGuard, OnboardedGuard] },
];
export const appRouting = RouterModule.forRoot(APP_ROUTES, {enableTracing: true});
With this setup it works fine
After trying to have lazy loading
example module
const EXAMPLE_ROUTES: Routes = [
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{
path: 'edit/sdg-info', component: SdgInfoComponent
}
]}
];
export const exampleRouting = RouterModule.forChild(EXAMPLE_ROUTES);
and app routing becomes
const APP_ROUTES: Routes = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', loadChildren: './example/example.module#ExampleModule', canActivate: [AuthGuard, OnboardedGuard] }
];
export const appRouting = RouterModule.forRoot(APP_ROUTES, {enableTracing: true});
The problem I'm facing is, the example route works fine, now the /search route breaks, as the router for some reason tries to match it with opportunity route (path: ':id')
What might be going wrong here?
This issue can occoure when you first implement your FeatureModule in your RootModule and after a given time you decide you want to load this FeatureModule lazy via loadChildren and you forgot to remove FeatureModule from your imports in your RootModule.
In your case your Routing Configuration will look something like this after compilation (PSEUDO-CODE):
const Routes_CONFIG = [
{ path: '', component: HomeComponent},
{ path: 'search', component: SearchComponent },
{ path: 'example', loadChildren: './example/example.module#ExampleModule', canActivate: [AuthGuard, OnboardedGuard] }
{ path: 'new', component: AddOpportunityComponent },
{ path: ':id', component: OpportunityProfileComponent,
children: [
{ path: 'edit/sdg-info', component: SdgInfoComponent }
]
}
]
In your case, when you just enter /search you will match :id OpportunityProfileComponent. That's because the router accepts the first route that matches a navigation request path.

How to make an optional root state in angular 2?

i need to do an optional prefix indicating on the language.
So you can go to
random-domain.com/
the default language will be selected(en)
and if you with selected language
random-domain.com/ru
language will be selected - ru
And this should apply to nested routes
random-domain.com/some-rand-entity and random-domain.com/ru/some-rand-entity
my non-working solution - an example
const app_common: Routes = [ ...];
export const app_routes: Routes = [
{
path: '',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
pathMatch: 'full'
}
];
export const lang_routes: Routes = [
{
path: ':lang',
component: HomeComponent,
resolve: {
languages: LanguagesStore
},
children: app_common,
pathMatch: 'full'
}
];
export const routes: Routes = [
...app_routes,
...app_common,
...lang_routes,
...checkoutRoutes
];
You can use route parameters for this purpose
export const app_routes: Routes = [
{
path: '',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
pathMatch: 'full',
children: app_common
},
{
path: ':lang',
component: HomeComponent,
resolve: {
settings: SettingsStore
},
children: app_common,
}
];
See also https://angular.io/docs/ts/latest/guide/router.html#!#route-parameters
This is something that should be handled with query parameters
url?lang=en
not with path parameters
url/en // don't do this
To add query params in routerLinks you would do
<a [routerLink]="..." [queryParams]="{ lang: 'en' }" >link</a>
To do with programmatically with Router, you would use
this.router.navigate(['...'], { queryParams: { lang: 'en' }});
To access the query params in a component, the ActivatedRoute has a queryParams property
this.route.queryParams.subscribe(params => {})
We can also preserve the query parameters so we don't need to keep applying them. In the routerLink we would do
<a [routerLink]="..." [queryParams]="{ lang: 'en' }" preserveQueryParams>link</a>
In the Router we would do
this.router.navigate(['...'], { preserveQueryParams: true});
What this does, is that when the current route has query params attached, when we navigate, the params will be automatically attached.
See Also:
Query Parameters and Fragments
Docs for RouterLink

Categories

Resources