I'm fairly new to vue.js and I'm currently trying to setup my different routes. I'm using sub routes, since the "logged in" user will have a different UI than a visitor.
Currently my setup is like this:
routes: [
{
path: '/auth',
name: 'auth',
component: test,
meta: {
auth: false
},
children: [
{
path: 'login',
name: 'login',
component: login
},
{
path: 'signup',
name: 'signup',
component: signup
}
]
},
{
path: '/user',
name: 'user',
component: test,
meta: {
auth: true
},
children: [
{
path: 'profile',
name: 'profile',
component: login
}
]
}
]
While this is working, I'm wondering why child routes don't take over the parents meta properties. Do I need to assign the meta.auth to each sub route? Or is there any way to inherit this?
Essentially in the router.beforeEach, I want to check if the user is authenticated correctly or not. But only on child routes of /user
I'm also coming from an angular background, so I'm used to nesting routes, not sure if this is the best way in Vue.
To answer my own question: https://github.com/vuejs/vue-router/issues/704
I didn't realise this was deprecated in Vue-router 2.0, it is possible to get the matched route and find the meta there.
With vue-router v.3 to match parent's meta (for example: in beforeEach() func. ) You need to use to.matched.some() like this:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.auth)) {
// ...
next({name:'route-name'})
} else {
next()
}
}
https://router.vuejs.org/guide/advanced/meta.html
Related
In my Angular project I've got:
SignInComponent -> Handling the login requests
DashboardComponent -> Displayed for all children when user has successfully logged in
HomeComponent -> The actual content/page that will be displayed to the user - A child of 'DashboardComponent'
And it looks like:
export const appRoutes: Routes = [
{
path: 'login', component: SignInComponent
},
{
path: '', component: DashboardComponent,
children: [
{ path: '', component: HomeComponent },
],
canActivate: [AuthGuard]
},
{
path: '', redirectTo: '/login', pathMatch: 'prefix'
}
]
Now the problem that I'm facing, is that when the user is successfully logged in, that it won't reload the component 'DashboardComponent'. And I'm not referring to the routes itself (those are going fine). But there's one needed JS script not loaded which blocks the user from expanding the menu item(s). See below:
However, when you manually reload the page, it will work. The menu item(s) will expand. See below:
So, fully reloading the component would do the trick, but I only want that when it's matching with the previous 'route', in this case '/login'. In other words, I would to fully reload the 'DashboardComponent', only when it's not a 'child'. How could I apply this?
Or is there perhaps a better and easier approach?
Here it looks some url match problem because you have defined path:'' to dashboard also making that path to redirect to login with next routing object in routes array
export const appRoutes: Routes = [
{
path: 'login', component: SignInComponent
},
{
path: 'dashboard', component: DashboardComponent,
children: [
{ path: 'home', component: HomeComponent },
],
canActivate: [AuthGuard]
},
{
path: '', redirectTo: '/login', pathMatch: 'prefix'
}
]
So change it like above code and try. This will not make any url confusion and redirection will take place properly
Update:
It seems that custom code (JS) is being called on document ready event. That explains why it's working the only first time. See comment: https://stackoverflow.com/a/46349639/2318669.
What I've done to solve it:
I declared a variable:
declare const openMobileMenu: any;
And then I bind it from the component:
onMobile() {
openMobileMenu();
}
To the following method in the JS file:
function openMobileMenu() {
$(".horizontal-menu .bottom-navbar").toggleClass("header-toggled");
};
Thanks anyway for the support! :)
I appreciate it.
I have
// routes.js
{ path: '/posts', name: 'Posts', component: PostsView },
{
path: '/post/:post_id',
name: 'PostRead',
component: PostReadView,
},
{
path: '/post/cu/:post_id?',
name: 'PostCreateUpdate',
component: PostCreateUpdateView,
},
// PostCreateUpdate.vue
mounted: function() {
if( this.$route.params.post_id ) {
this.$store.dispatch('getPost', this.$route.params.post_id);
}
},
When I access the PostCreateUpdate via router-link like this
<router-link :to="{ name: 'PostCreateUpdate' }">Create</router-link>
It works with no problems as I see the parameter in the Vue Devtools isn't set, but when I access the URL by reloading or hard coding the url /post/cu/ the framework (I think) removes the trailing slash and treats cu as some /post/ parameter, thus, loading PostRead with post_id=cu and giving me something I don't want.
You need to always declare your most restrictive URIs first. Order matters, because Vue Router will go through your routes, and pick the first one that matches.
Invert your /post/:post_id route and /post/cu/:post_id? one:
// routes.js
{ path: '/posts', name: 'Posts', component: PostsView },
{
path: '/post/cu/:post_id?',
name: 'PostCreateUpdate',
component: PostCreateUpdateView,
},
{
path: '/post/:post_id',
name: 'PostRead',
component: PostReadView,
},
i have two routes :-
1- http://localhost:4200/members/10 ===> this for member's page
2- http://localhost:4200/members/10?tab=3 ===> this for chat page
I want to make chat as a paid service so I create component I called it charge with this route ==> http://localhost:4200/charge so if any member like to go to chat route he will be redirected to charge page as I create code in ngOnInit method in chat component like that
if(!this.authService.paid)
{this.router.navigate(['charge']);}
When I go chat it redirects me to charge page and that's cool , the problem is that when I go member'page it redirects me to charge page and that's not cool at all, so please help me what can i do to solve this problem, thanks in advance
and this is my routes
export const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{
path: '',
runGuardsAndResolvers: 'always'
, canActivate: [AuthGuard],
children: [
{
path: 'members', component: MemberListComponent, resolve: {
users: MemberListResolver
}
},
{
path: 'member/edit', component: MemberEditComponent, resolve: {
user: MemberEditResolver
}, canDeactivate: [PreventUnsavedChangesGuard]
},
{
path: 'members/:id', component: MemberDetailComponent, resolve: {
user: MemberDetailResolver
}
},
{
path: 'lists', component: ListsComponent, resolve: {
users: ListResolver
}
},
{ path: 'messages', component: MessagesComponent, resolve: { messages: MessageResolver }, canActivate: [MessagesGuard] },
{ path: 'charge', component: PaymentComponent }
]
},
{ path: '**', redirectTo: '', pathMatch: 'full' }
];
It looks like you use the same ngOnInit implementation for both pages '/member' and '/chat'. And if this !this.authService.payed returns true, you will always be redirected to '/charge' page.
But to have a better understanding, please provide your routing configuration.
Edit:
Thank you for adding your routes.
{
path: 'members/:id', component: MemberDetailComponent, resolve: {
user: MemberDetailResolver
}
}
It seems like you check for !this.authService.payed in MemberDetailComponent#ngOnInit, but you probably do not check your queryParam ?tab=3.
To fix this issue quickly you can modify your if-condition:
if(!this.authService.payed && this.route.snapshot.queryParams['tab'] === 3)
where this.route has to be injected via constructor parameter
constructor(private route: ActivatedRoute)
But
I think the best solution for this issue would be to add another child route for chat page and handle authorization with another 'canActivate'.
I'm trying to use the auxiliary route on an empty path. For example:
{
path: 'users',
children: [
{
path: '',
component: UsersComponent,
},
{
path: 'user-details',
outlet: 'list',
component: UserDetailsComponent
},
]
},
And my UsersComponent template:
<router-outlet></router-outlet>
<router-outlet name="list"></router-outlet>
But when I'm trying to navigate to the following URLs:
1. http://localhost:4200/users(list:user-details)
2. http://localhost:4200/(users//list:user-details)
I'm getting this error:
Cannot match any routes. URL Segment: 'users'
You are getting that error because you have no component loading for 'users' which you set as your first route. the 'users' route should be defined in your main routing module like this
{ path: 'users', loadChildren: './users/user.module#UserModule' }
and your current code needs to look like this
const userRoutes: Routes = [
{
path: '', component: UsersComponent, children: [
{
path: 'user-details',
outlet: 'list',
component: UserDetailsComponent
}
]
}
and that will make the firs route 'users'
I would like to serve my Vue.js app from a subdirectory on a staging server. For example: http://url.com/subdir/app/
Right now if I do this and set up the build config assetsPublicPath to serve from that folder, all the assets are served fine but my app does not get routed correctly. The "home" page gets routed to the 'catch-all', and any further routes simply show the normal white-page 404.
Here is my router:
export default new Router({
mode: 'history',
routes: [
{
path: '/',
component: ContentView,
children: [
{
path: '/',
name: 'DataTable',
component: DataTable,
meta: { requiresAuth: true }
},
// ===================================
// Login
// ===================================
{
path: '/login',
name: 'AppLogin',
component: AppLogin,
meta: { checkAlreadyLoggedIn: true }
},
{
path: '/logout',
name: 'AppLogout',
component: AppLogout,
meta: { requiresAuth: true }
}
]
},
{
path: '*',
component: ContentView,
children: [
{
path: '/',
name: 'NotFound',
component: NotFound
}
]
}
]})
And here is the necessary config/index.js changes: assetsPublicPath: '/subdir/app/'
In local development the routes work fine. But on the staging server all static assets, the built JS and CSS etc all serve fine. However the home route shows the catch-all. I am assuming it's because my routes are not set up correctly, or because I need to do something to serve from a subdirectory in production.
The assetsPublicPath config is just for webpack assets. For vue-router, you need to set the base option in the constructor.
See docs: https://router.vuejs.org/en/api/options.html#base
I have been able to solve this, using the base property of vue-route.
In the case of the example it would look like this:
export default new Router({
mode: 'history',
base: '/subdir/app/',
routes: [
{
path: '/',
component: ContentView,
children: [
My question now is how can I make this subdirectory dynamically.
Imagine a single server, and 2 different urls pointing to this server.
www.dominio / app1
www.dominio / app2