Home > Blockchain >  How to correctly handle 404 when using modular routing in Angular 10
How to correctly handle 404 when using modular routing in Angular 10

Time:11-21

I'm failing to properly handle 404 pages in an Angular 10 app using modular routing.

My code structure is as follows:

|> app
|-- app.module.ts
|-- app-routing.module.ts
|-- app.component{ts, spec.ts, scss, html}
|-> pages
|--- pages.module.ts
|--> home-page
|---- home-page.module.ts
|---- home-page-routing.module.ts
|---> home-page
|----- home-page.component{ts, spec.ts, scss, html}
|--> test-page
|---- test-page.module.ts
|---- test-page-routing.module.ts
|---> test-page
|----- test-page.component{ts, spec.ts, scss, html}

The (truncated) global app-routing module has 404 handler configured as such:

...
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },

  // If the following line is not commented out,
  // You are unable to navigate to either the 'Home' or 'Test' pages.
  // { path: '**', component: PageNotFoundComponent },
];

...

The problem I'm having is that Angular matches the global 404 handler in ./app/app-routing.module.ts & resolves to that route.

Here's a short stackblitz that provides an example of my experience (Note: Stackblitz sample is actually running Ng12, while our app is running Ng10 - both exhibit the same behavior)

My goal is to get a global 404 handler OR redirect working, while continuing to keep all our page routes defined in their respective module-routing files.

Can this be done, if so - how?

CodePudding user response:

I looked at your Stackblitz and the issue is that the AppRoutingModule is imported before the PagesModule.

You should import the PagesModule first because their routes have higher priority.

  imports: [
    BrowserModule,
    RouterModule,
    FormsModule,
    PagesModule,
    AppRoutingModule,
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

Another (better) solution would be to lazy load the module:

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  {
    path: '',
    loadChildren: () =>
      import('./pages/pages.module').then((m) => m.PagesModule),
  },
  { path: '**', component: PageNotFoundComponent },
];

This way you wont have to import the whole PagesModule into your AppModule.

  • Related