Search code examples
angularrouter

Angular 7 Router keep redirecting me to the 404 not found page


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

Solution

  • 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.

    1. Here is Code Editor : https://stackblitz.com/edit/angular-j15tsc
    2. Here is Demo APP : https://angular-j15tsc.stackblitz.io

    Changes Made

    1. Usage of RouterLink in navigation.component.html file Changed
    2. Order of PageNotFoundComponent in app-routing.module.ts file in router array.