40

When using child routes with angular2's router "3.0", there is no need to declare them in the parent router config (before, you had to do something like /child... in the parent component).

I want to configure a global "page not found" handler, which I can do like this:

{ path: '**', component: PageNotFoundComponent } 

in my app routing module.

The caveat: If I do this, the router navigates to routes declared in the app routing module before the PageNotFoundComponent just fine. But it always navigates to the wildcard route when I try to access a child route (declared using RouterModule.forChild in some child routing module.

Intuitively, the wildcard route should be placed behind all other route configs, because the router resolves in declaration order. But there does not seem to be a way to declare it after the child routes. It also does not seem very elegant to declare a wildcard route in all child router modules.

Am I missing something or is there just no way to define a global 404-page in Angular-2-Router-3 when using child routes?

1
  • 1
    Today (version 5) it seems not be a case any more. The more specific paths seem to be matched before trying less specific, no matter the order of declaration. Commented Feb 22, 2018 at 12:04

3 Answers 3

48

You can easily have a centralized wildcard route, i.e. for a site-wide 'Page not found' component. It simply has to be extracted into a separate routing module, which gets included after all the other modules containing child routes.

Therefore, the wildcard route is truly in last position and doesn't hide the routes from any following module.

The wildcard routing module or 'page not found' routing module:

@NgModule({ imports: [ RouterModule.forChild([ { path: '**', component: NotFoundComponent } ]) ], declarations: [ NotFoundComponent ], exports: [ RouterModule ] }) export class WildcardRoutingModule { } 

The application module :

@NgModule({ imports: [ BrowserModule, AppRoutingModule, // Has forRoot routes HomeModule, // Has forChild routes LoginModule, // Has forChild routes ProductModule, // Has forChild routes DiagnosticsModule, // Has forChild routes WildcardRoutingModule // Last position ], declarations: [ AppComponent ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { } 
Sign up to request clarification or add additional context in comments.

6 Comments

One little thing: The NotFoundComponent has to be declared somewhere. I did that in the 'page not found' routing module.
neat! I was also trying to figure this out. I realized based on this solution, an alternative way to do it is to just import the AppRoutingModule after all the child modules.
@David: Just added it to the WildcardRoutingModule.
Thanks @David I really like you! Best question ever and now best comment ever too :)
@MathieuRenda - What to do for lazy loaded modules ?
|
24

Simple solution is to reorder modules in the 'imports' array in app module file - ensure app/root router is the last item in the array; for example

 @NgModule({ imports: [FeatureModule1, FeatureModule2, FeatureModule3, AppRouterModule] ... ... }) 

2 Comments

Even with this, i still got app routing config sits above feature routing configs.
Yeap, order is important
2

I have the following example for you. The /-route redirects to the /app-route and shows the StartComponent inside the <router-outlet> of your parent AppComponent. The StartComponent itself has another <router-outlet> in its template in which the router loads the child components.

const appRoutes: Routes = [ { path: '', redirectTo: 'app', pathMatch: 'full', }, { path: 'app', component: StartComponent, children: [ { path: '', redirectTo: 'welcome' }, { path: 'welcome', component: WelcomeComponent }, { path: 'settings', component: SettingsComponent }, ] }, { path: '**', component: PageNotFoundComponent } ]; 

The last route is the wildcard route with the **-path. It will be shown if you navigate to a not known URL like /test123 or for the child components /app/test123.

The pathMatch: 'full' means that the router is looking for a equal route. It is important for the redirects.

If you also need a PageNotFoundComponent for your children, you can add a wildcard to them too.

{ path: 'app', component: StartComponent, children: [ { path: '', redirectTo: 'welcome' }, { path: 'welcome', component: WelcomeComponent }, { path: '**', component: ChildrenPageNotFoundComponent }, ] } 

3 Comments

Thank you for your answer. What you describe is not exactly the case I had in mind - I was thinking of the example in Milestone #4 on angular.io/docs/ts/latest/guide/router.html. They have routes defined in the crisis-center-routing.module.ts, but none in the app-routing.module.ts. I would like to define the global 404 handler in the app routing module.
I need this as well, as my feature modules define their own routes.
Does path: '**' covers path:'' ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.