I have a small Angular 7 project, where I have embedded the <router-outlet></router-outlet>
directive within a navigation
component. When I click on a link to navigate to a different path, the router initial redirects to that path, but then routes to the base URL, which then routes to a 404 page I have setup.
Can someone advise what I may be doing wrong? I suspect it's how I am using the navigation
component.
src\app\app-routing.module.ts
const routes: Routes = [
{
path: 'lunch-forms',
component: LunchFormsComponent,
children: [],
},
{
path: 'profile',
component: UserProfileComponent,
children: [],
},
{
path: 'teachers',
component: TeacherListComponent,
children: [],
},
{
path: 'login',
component: LoginComponent,
children: [],
},
{ path: '**', component: PageNotFoundComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
];
@NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
src\app\app.component.html
<div>
<app-navigation></app-navigation>
</div>
src\app\components\navigation\navigation.component.html
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-card class="profile-card" *ngIf="user">
<mat-card-header>
<div mat-card-avatar
class="profile-header-image"
[ngStyle]="{'background-image': 'url(' + user.photoURL + ')'}"></div>
<mat-card-title>{{ user.displayName }}</mat-card-title>
<mat-card-subtitle>{{ user.email }}</mat-card-subtitle>
</mat-card-header>
</mat-card>
<mat-nav-list>
<a mat-list-item href="#" (click)="this.router.navigate(['/'])">Welcome</a>
<a mat-list-item href="#" (click)="this.router.navigate(['/lunch-forms'])">Lunch Forms</a>
<a mat-list-item href="#" (click)="this.router.navigate(['/profile'])">Profile</a>
<a mat-list-item href="#" (click)="this.router.navigate(['/teachers'])">Teachers</a>
<a mat-list-item href="#" (click)="logout()">Logout</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>TCS Lunch Forms</span>
</mat-toolbar>
<!-- Content -->
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
src\app\components\navigation\navigation.component.ts
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { AuthService } from 'src/app/services/auth.service';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent {
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
constructor(
private authService: AuthService,
private breakpointObserver: BreakpointObserver,
private router: Router) {}
isLoggedIn(): boolean {
return this.authService.authenticated;
}
logout(): void {
this.authService.logout();
this.router.navigate(['']);
}
get user(): firebase.User {
return this.authService.user;
}
}
Router debugging output:
Router Event: NavigationStart platform-browser.js:1075
NavigationStart(id: 2, url: '/lunch-forms') platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", navigationTrigger: "imperative", restoredState: null }
platform-browser.js:1066
Router Event: RoutesRecognized platform-browser.js:1075
RoutesRecognized(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms', state: Route(url:'', path:'') { Route(url:'lunch-forms', path:'lunch-forms') } ) platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms", state: {…} }
platform-browser.js:1066
Router Event: GuardsCheckStart platform-browser.js:1075
GuardsCheckStart(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms', state: Route(url:'', path:'') { Route(url:'lunch-forms', path:'lunch-forms') } ) platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms", state: {…} }
platform-browser.js:1066
Router Event: ChildActivationStart platform-browser.js:1075
ChildActivationStart(path: '') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: ActivationStart platform-browser.js:1075
ActivationStart(path: 'lunch-forms') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: GuardsCheckEnd platform-browser.js:1075
GuardsCheckEnd(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms', state: Route(url:'', path:'') { Route(url:'lunch-forms', path:'lunch-forms') } , shouldActivate: true) platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms", state: {…}, shouldActivate: true }
platform-browser.js:1066
Router Event: ResolveStart platform-browser.js:1075
ResolveStart(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms', state: Route(url:'', path:'') { Route(url:'lunch-forms', path:'lunch-forms') } ) platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms", state: {…} }
platform-browser.js:1066
Router Event: ResolveEnd platform-browser.js:1075
ResolveEnd(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms', state: Route(url:'', path:'') { Route(url:'lunch-forms', path:'lunch-forms') } ) platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms", state: {…} }
platform-browser.js:1066
Router Event: ActivationEnd platform-browser.js:1075
ActivationEnd(path: 'lunch-forms') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: ChildActivationEnd platform-browser.js:1075
ChildActivationEnd(path: '') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: NavigationEnd platform-browser.js:1075
NavigationEnd(id: 2, url: '/lunch-forms', urlAfterRedirects: '/lunch-forms') platform-browser.js:1066
Object { id: 2, url: "/lunch-forms", urlAfterRedirects: "/lunch-forms" }
platform-browser.js:1066
Router Event: Scroll platform-browser.js:1075
Scroll(anchor: 'null', position: 'null') platform-browser.js:1066
Object { routerEvent: {…}, position: null, anchor: null }
platform-browser.js:1066
Navigated to http://localhost:4200/#
[WDS] Disconnected! client:172
Router Event: NavigationStart platform-browser.js:1075
NavigationStart(id: 1, url: '/') platform-browser.js:1066
Object { id: 1, url: "/", navigationTrigger: "imperative", restoredState: null }
platform-browser.js:1066
Angular is running in the development mode. Call enableProdMode() to enable the production mode. core.js:38780
Router Event: RoutesRecognized platform-browser.js:1075
RoutesRecognized(id: 1, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'**') } ) platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/", state: {…} }
platform-browser.js:1066
Router Event: GuardsCheckStart platform-browser.js:1075
GuardsCheckStart(id: 1, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'**') } ) platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/", state: {…} }
platform-browser.js:1066
Router Event: ChildActivationStart platform-browser.js:1075
ChildActivationStart(path: '') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: ActivationStart platform-browser.js:1075
ActivationStart(path: '**') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: GuardsCheckEnd platform-browser.js:1075
GuardsCheckEnd(id: 1, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'**') } , shouldActivate: true) platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/", state: {…}, shouldActivate: true }
platform-browser.js:1066
Router Event: ResolveStart platform-browser.js:1075
ResolveStart(id: 1, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'**') } ) platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/", state: {…} }
platform-browser.js:1066
Router Event: ResolveEnd platform-browser.js:1075
ResolveEnd(id: 1, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'**') } ) platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/", state: {…} }
platform-browser.js:1066
Router Event: ActivationEnd platform-browser.js:1075
ActivationEnd(path: '**') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: ChildActivationEnd platform-browser.js:1075
ChildActivationEnd(path: '') platform-browser.js:1066
Object { snapshot: {…} }
platform-browser.js:1066
Router Event: NavigationEnd platform-browser.js:1075
NavigationEnd(id: 1, url: '/', urlAfterRedirects: '/') platform-browser.js:1066
Object { id: 1, url: "/", urlAfterRedirects: "/" }
platform-browser.js:1066
Router Event: Scroll platform-browser.js:1075
Scroll(anchor: 'null', position: 'null') platform-browser.js:1066
Object { routerEvent: {…}, position: null, anchor: null }
platform-browser.js:1066
You should be doing routing using built-in RouterLink directive of angular. Here is stack blitz demo where You can check how to work with RouterLink. Your same components are used to demonstrate how to route the components on navigation component.
Changes Made
navigation.component.html
file ChangedPageNotFoundComponent
in app-routing.module.ts
file in
router array.