Issue with Angular 2: Unable to display 404 error page

I have created a custom "404 - page not found" page to handle situations where the user enters a URL that does not match any paths in my web app:

export const routerConfig: Routes = [
   {
      component: LandingPageComponent,
      path: "",
   },
   {
      component: ProfilePageComponent,
      path: "profile",
   },
   {
      component: NotFoundPageComponent,
      path: "**",
   },
];

However, when I type in my app address followed by an incorrect path (e.g. http://localhost:3000/prcds), it simply shows:

Cannot GET /prcds

On a blank web page with an error message in the console:

Failed to load resource: the server responded with a status of 404 (Not Found)

I have already imported NotFoundPageModule into my app.module.

To resolve this issue, I referred to the "configuration" section on the Angular documentation website (https://angular.io/docs/ts/latest/guide/router.html) and adapted their approach for setting up the 404 notfound page in my project.

How can I prevent the display of the error message and instead show the custom 404 error page I designed?

The error page is similar to the one mentioned in another query, so there might be a connection to this issue:

My Code:

File structure of the not found page:

https://i.sstatic.net/PeKUv.png

notfoundpage.component.ts

import { Component } from "@angular/core";
import { Title } from "@angular/platform-browser";

@Component({
   selector: "not-found-page",
   styleUrls: ["dist/app/components/not-found-page/not-found-page.component.css"],
   templateUrl: "dist/app/components/not-found-page/not-found-page.component.html",
})
export class NotFoundPageComponent {
   constructor(private titleService: Title) {
      this.titleService.setTitle("Not Found");
   }
}

notfoundpage.module.ts

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import * as NotFoundPage from "./index";

@NgModule({
   declarations: [
      NotFoundPage.NotFoundPageComponent,
   ],
   exports: [NotFoundPage.NotFoundPageComponent],
   imports: [CommonModule, FormsModule],
})
export class NotFoundPageModule { }

app.module.ts

// tslint:disable-next-line:no-reference
/// <reference path="../../../node_modules/moment/moment.d.ts" />

// Angular 2 modules
import { Component, NgModule } from "@angular/core";
import {
   ControlValueAccessor,
   FormBuilder,
   FormGroup,
   FormsModule,
   ReactiveFormsModule,
   Validators,
} from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { RouterModule } from "@angular/router";
import { AgmCoreModule } from "angular2-google-maps/core";
import { routerConfig } from "../app.routes";

// Plugin modules
import { Ng2Bs3ModalModule } from "ng2-bs3-modal/ng2-bs3-modal";

// App modules
import { AboutPageModule } from "../components/about-page/about-page.module";
import { AddPageModule } from "../components/add-page/add-page.module";
import { FindPageModule } from "../components/find-page/find-page.module";
import { LandingPageModule } from "../components/landing-page/landing-page.module";
import { NotFoundPageModule } from "../components/not-found-page/not-found-page.module";
import { ProfilePageModule } from "../components/profile-page/profile-page.module";
import { RegisterPageModule } from "../components/register-page/register-page.module";
import { SharedModule } from "../components/shared/shared.module";
import { AppComponent } from "./app.component";

@NgModule({
   bootstrap: [AppComponent],
   declarations: [
      AppComponent,
   ],
   imports: [
      BrowserModule,
      RouterModule.forRoot(routerConfig),
      FormsModule,
      Ng2Bs3ModalModule,
      AgmCoreModule,
      ReactiveFormsModule,
      LandingPageModule,
      FindPageModule,
      AddPageModule,
      AboutPageModule,
      RegisterPageModule,
      ProfilePageModule,
      NotFoundPageModule,
      SharedModule,
   ],
   providers: [
      FormBuilder,
   ],
})
export class AppModule { }

Complete app.routes.ts:

import { Routes } from "@angular/router";
import { AboutPageComponent } from "./components/about-page/about-page.component";
import { AddPageComponent } from "./components/add-page/add-page.component";
import { FindPageComponent } from "./components/find-page/find-page.component";
import { LandingPageComponent } from "./components/landing-page/landing-page.component";
import { NotFoundPageComponent } from "./components/not-found-page/not-found-page.component";
import { ProfilePageComponent } from "./components/profile-page/profile-page.component";
import { RegisterPageComponent } from "./components/register-page/register-page.component";

export const routerConfig: Routes = [
   {
      component: LandingPageComponent,
      path: "",
   },
   {
      path: "",
      pathMatch: "full",
      redirectTo: "",
   },
   {
      component: FindPageComponent,
      path: "find",
   },
   {
      component: AddPageComponent,
      path: "add",
   },
   {
      component: RegisterPageComponent,
      path: "register",
   },
   {
      component: AboutPageComponent,
      path: "about",
   },
   {
      component: ProfilePageComponent,
      path: "profile",
   },
   {
      path: "**",
      pathMatch: "full",
      redirectTo: "NotFoundPageComponent",
   },
   {
      component: ProfilePageComponent,
      path: "**",
   },
];

Answer №1

Update your app.routes.ts file with the code snippet provided below:

import { Routes, RouterModule } from "@angular/router";
import { AboutPageComponent } from "./components/about-page/about-page.component";
import { AddPageComponent } from "./components/add-page/add-page.component";
import { FindPageComponent } from "./components/find-page/find-page.component";
import { LandingPageComponent } from "./components/landing-page/landing-page.component";
import { NotFoundPageComponent } from "./components/not-found-page/not-found-page.component";
import { ProfilePageComponent } from "./components/profile-page/profile-page.component";
import { RegisterPageComponent } from "./components/register-page/register-page.component";

const routes: Routes = [
   {
      component: LandingPageComponent,
      path: "",
   },
   {
      component: FindPageComponent,
      path: "find",
   },
   {
      component: AddPageComponent,
      path: "add",
   },
   {
      component: RegisterPageComponent,
      path: "register",
   },
   {
      component: AboutPageComponent,
      path: "about",
   },
   {
      component: ProfilePageComponent,
      path: "profile",
   },
   {
      component: NotFoundPageComponent,
      path: "404",
   },
   {
      path: "**",
      redirectTo: '404' 
   }
];

export const routerConfiguration = RouterModule.forRoot(routes);

Answer №2

To ensure proper routing, make sure to include pathMatch: 'full' as shown below:

        export const appRoutes: Routes = [
           {
              component: HomePageComponent,
              path: "",
           },
           {
              component: AboutPageComponent,
              path: "about",
           },
            { path: '', redirectTo: 'ErrorPageComponent', pathMatch: 'full' },
           {
              component: ErrorPageComponent,
              path: "**",
           },
        ];

In your "error.module.ts" file, follow these steps:

Replace the following code:

       import * as Error from "./index";

With this:

        import {ErrorPageComponent } from './error-page.component';

Then replace this code block:

     declarations: [
          Error.ErrorPageComponent,
       ],
       exports: [Error.ErrorPageComponent]

With the updated version:

         declarations: [
              ErrorPageComponent,
           ],
           exports: [ErrorPageComponent]

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling to implement a singleton service in Angular as per the documentation provided

I have implemented a service in Angular that I want to be a singleton. Following the guidelines provided in the official documentation, I have set the providedIn property to "root" as shown below: @Injectable({ providedIn: "root" }) export class SecuritySe ...

Specialized Sonar JavaScript plugin rule designed to identify specific method calls throughout various source files

In my quest to develop a specialized rule for the Sonar javascript plugin, I am focusing on verifying whether an init() function is invoked within a set of JS source files. To kick things off, I subscribe to call expressions: public void init() { subs ...

Tips on locating file encoding and decoding?

I have been tasked with understanding the decoding process of a file left on my system by Spotify. The specific file is named context_player_state_restore and can be found in the directory /Users/<myuser>/Library/Application Support/Spotify/Persiste ...

Halt period indicated in the document specifying the designated timeframe

If I have two files named index.php and fetch.php The contents of index.php are as follows: <script> $(document).ready(function(){ setInterval(function(){ $('#fetch').load('fetch.php') }, 1000); }); </sc ...

A guide on creating a Javascript leap year algorithm using Test-Driven Development techniques

Currently, I am working on crafting a leap year algorithm by utilizing a TDD suite. This marks my initial venture into the realm of TDD. Displayed below is the code extracted from the spec file. var Year = require('./leap'); describe('Lea ...

Need for a DatePicker in a dynamic form

I have implemented a reactive form that includes a Datepicker component. <div class="form-group"> <label class="form-control-label" for="field_dataAtivacao">Data Ativação</label> <div class="input-group"> < ...

Creating a stunning 2D image from a 3D scene through the power of raytracing with webgl and three.js

My goal is to project a 3D scene onto a 2D plane using ray tracing. Although my ultimate aim is volume rendering, I am currently struggling with the basics. I have set up a three.js scene with the viewing plane attached to the camera in front of it. The S ...

I am having trouble viewing the input value on my Angular5 form

Here is the HTML code snippet that I've written: <input type="text" name="fechainscripcion" #fechainscripcion="ngModel" [(ngModel)]="alumno.fechainscripcion" value="{{today | date:'dd/MM/yyyy'}}" class="form-control" /> This is a seg ...

What is the method to retrieve the index of a matching element from a JSON object?

var radioRenderData = [{ "type": "radio-group", "label": "Radio Group", "className": "radio-group", "name": "radio-group-1479370460494", "values": [{ "label": "Option A", "value": "option-a", "selected": false }, { "label": "Opt ...

What is the process for inserting HTML content into the body of an iframe?

Is there a way to insert HTML content into the body of an iframe instead of using the src attribute to call a page's URL? I am looking for a code that is compatible with all browsers and works perfectly. ...

Is it possible for me to utilize the webAudio API in Chrome to connect to the local audio output stream?

Currently, I am working on audio analysis for a visualizer application running on my computer. I am wondering if there is a way to directly access the output audio data stream from the browser? For this project, I am using JavaScript along with the three ...

The custom native date adapter is facing compatibility issues following the upgrade of Angular/Material from version 5 to 6

In my Angular 5 application, I had implemented a custom date adapter as follows: import {NativeDateAdapter} from "@angular/material"; import {Injectable} from "@angular/core"; @Injectable() export class CustomDateAdapter extends NativeDateAdapter { ...

Utilize jQuery to locate a specific value within a collapsible Bootstrap 4 table

Is it possible to use a Bootstrap 4 table inside a collapse? I need to search for a specific value in the table and if the value is found, I want to open the collapse and display the row containing that value. <div id="collapseStudents" class="collapse ...

Issue with Bootstrap 4 nested collapse: "data-parent" attribute malfunctioning

I'm looking to implement the collapse data-parent options in a way that mimics traditional accordion behavior: all collapsible elements under a specified parent should close when a new one is opened. However, I am encountering issues with this setup. ...

What steps can I take to ensure TypeScript compiler approves of variance in calling generic handlers, such as those used in expressJS middleware?

disclaimer: I am a bit uncertain about variance in general... Here is the scenario I am facing: // index.ts import express from 'express'; import {Request, Response} from 'express'; const app = express(); app.use(handler); interface ...

Choosing read-only text fields using JQuery

I am working on an ASP.NET MVC project and I am looking to select all text boxes with the "readOnly" attribute on the current page. Once identified, I want to trigger a modal jQuery dialog on keypress for each of these disabled text boxes. Any suggestion ...

The background on my modal remains unchanged

I have integrated a modal using Iframe for user login/registration on my website. Here is the HTML code: <div class="modal" id="ays-popin-connexion" aria-hidden="true"> <div class="modal-body" aria-hidden="true"> <iframe src=" ...

Step-by-step guide on building a personalized rxjs operator using destructured parameters

I am in the process of developing a unique RxJS filter operator that requires a destructured array as a parameter. Unfortunately, TypeScript seems to be throwing an error related to the type declaration: Error TS2493: Tuple type '[]' with a len ...

Restricting a generic parameter to a combination type in Typescript

Is there a method in Typescript to restrict a generic parameter to only accept a union type? To clarify my question, I wish that T extends UnionType would serve this purpose: function doSomethingWithUnion<T extends UnionType>(val: T) {} doSomethingW ...

"Can you provide guidance on binding data in vue.js when there is a dash (-) in the key of the JSON

My JSON data is structured as follows: { "color-1": "#8888", "color-2": "#000" } I am attempting to bind this variable with a style tag for a Vue component. However, my current approach seems to not be functioning as expected. <div v-bind:sty ...