Reputation: 9875
I am having trouble understanding my current issue where I am not able to load the new page when the routerlink
is clicked.
I have tried many different structures for the link but no matter what I change it to the error in the console says
VM39436:48 EXCEPTION: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'stream'
I am using to template layouts then making my pages children of those layouts. One layout is secure and one layout is public.
In app.routing.ts
const APP_ROUTES: Routes = [
{
path: '',
redirectTo: 'stream',
pathMatch: 'full',
},
{
path: 'profile',
component: SecureLayoutComponent,
data: {
title: 'Secure Views'
},
children: [
{
path: 'Profile',
loadChildren: 'profile/profile.module#ProfileModule'
}
]
},
{
path: '',
component: PublicLayoutComponent,
data: {
title: 'Public Views'
},
children: [
{
path: 'stream',
loadChildren: 'stream/stream.module#StreamModule',
}
]
}
];
Now I have a folder for profile and a folder for stream.
so when you move to stream directory this is the stream-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes,
RouterModule } from '@angular/router';
import { StreamComponent } from './stream.component';
const routes: Routes = [
{
path: '',
component: StreamComponent,
data: {
title: 'Stream'
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class StreamRoutingModule {}
And this is the profile-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes,
RouterModule } from '@angular/router';
import { ProfileComponent } from './profile.component';
export const routes: Routes = [
{
path: '',
data: {
title: 'Secure Pages'
},
children: [
{
path: 'profile',
component: ProfileComponent,
data: {
title: 'Profile Page'
}
}
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ProfileRoutingModule {}
So this loads fine when the app renders. But when I try to click,
<a class="nav-link" routerLinkActive="active" [routerLink]="['../profile/profile']">Profile</a>
Or
<a class="nav-link" routerLinkActive="active" [routerLink]="['../profile']">Profile</a>
or
<a class="nav-link" routerLinkActive="active" [routerLink]="['/profile']">Profile</a>
I get the error mentioned above,
So from the /
directory
/app.routing.ts
/stream/stream.component.ts
& stream-routing.module.ts
/profile/profile.component.ts
& profile-routing.module.ts
// Can't access this from public layout.
Upvotes: 1
Views: 5285
Reputation: 9875
I am adding this answer to help anyone else who is having problems with multi level routing, child routes, or auth guard.
I use two template in my apps,
/templates/public.component.ts
/templates/secure.component.ts
Here is the secure-layout.component.ts file
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Auth } from './../services/auth.service';
@Component({
providers: [ Auth ],
selector: 'app-dashboard',
templateUrl: './secure-layout.component.html'
})
export class SecureLayoutComponent implements OnInit {
constructor( private router: Router, private auth: Auth ) { }
ngOnInit(): void { }
}
Here is the public-layout.component.ts file
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Auth } from './../services/auth.service';
@Component({
providers: [ Auth ],
selector: 'app-dashboard',
templateUrl: './public-layout.component.html'
})
export class PublicLayoutComponent implements OnInit {
constructor( private router: Router, private auth: Auth ) { }
ngOnInit(): void { }
}
This way I can add guard to the secure template redirecting any unauthorized traffic back to the public template. So from the
/app.routing.ts
file I creates routes for the layouts then inside of the components I create I create child routes which become child routes to the respective template.
app.routing.ts
import { Routes, RouterModule } from "@angular/router";
import {Guard} from "./services/guard.service";
//Layouts
import { PublicLayoutComponent } from './layouts/public-layout.component';
import { SecureLayoutComponent } from './layouts/secure-layout.component';
import { STREAM_ROUTES } from "./stream/stream.routes";
import { PROFILE_ROUTES } from "./profile/profile.routes";
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/stream', pathMatch: 'full', },
{ path: '', component: PublicLayoutComponent, data: { title: 'Public Views' }, children: STREAM_ROUTES },
{ path: '', component: SecureLayoutComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: PROFILE_ROUTES }
];
export const routing = RouterModule.forRoot(APP_ROUTES);
/stream/stream.routes.ts
import { Component, OnInit } from '@angular/core';
@Component({
templateUrl: './stream.component.html',
})
export class StreamComponent {
constructor() { }
}
/profile/profile.routes.ts
import { Routes } from "@angular/router";
import { ProfileComponent } from './profile.component';
export const PROFILE_ROUTES: Routes = [
{ path: '', redirectTo: 'profile', pathMatch: 'full' },
{ path: 'profile', component: ProfileComponent }
];
In this example stream is where I keep my public views and profile is where all of my secure views will be. So if I wanted to create a new public view I would go into stream and create a new route then create the html file as well as component.ts file.
I hope this is helpful. I think this is a very nice way to handle routing for any app.
Upvotes: 1
Reputation: 657496
I think you just need to remove the redirect route
{
path: '',
redirectTo: 'stream',
pathMatch: 'full',
},
like
const APP_ROUTES: Routes = [
{
path: 'profile',
component: SecureLayoutComponent,
data: {
title: 'Secure Views'
},
children: [
{
path: 'Profile',
loadChildren: 'profile/profile.module#ProfileModule'
}
]
},
{
path: '',
component: PublicLayoutComponent,
data: {
title: 'Public Views'
},
children: [
{
path: 'stream',
loadChildren: 'stream/stream.module#StreamModule',
}
]
}
];
Upvotes: 1