2

I would like to have a routing module in my main app plus routing in a separate module, like:

app
 - modules
   -my-module
      my-routing.module.ts
 app-routing.module.ts

The main routing module has:

const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'view-container' },
  { path: 'view-container', component: ViewContainerComponent },
  { path:  '**', component: ViewContainerComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { enableTracing: true })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

The sub module's routing is:

const routes: Routes = [
  { path: 'view-detail', component: CompADetailComponent }
];

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild(routes)
  ],
  declarations: []
})
export class MyRoutingModule { }

My ViewContainer component has a routerLink to "view-detail".

<a [routerLink]="['/view-detail']">
  View Details
</a>

However, when I click on the "View Details" link, only the URL changes, the CompADetailComponent is not loaded.

I do note that if I move the "view-detail" path to the main app routing module it works fine. In the tracing, the difference I see is:

When it works:

Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 2, url: '/view-detail')
platform-browser.js:367 NavigationStart {id: 2, url: "/view-detail"}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'view-detail') } )
platform-browser.js:367 RoutesRecognized {id: 2, url: "/view-detail", urlAfterRedirects: "/view-detail", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: GuardsCheckStart
platform-browser.js:367 GuardsCheckStart(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'view-detail') } )
platform-browser.js:367 GuardsCheckStart {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: 'view-detail')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: GuardsCheckEnd
platform-browser.js:367 GuardsCheckEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'view-detail') } , shouldActivate: true)
platform-browser.js:367 GuardsCheckEnd {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, shouldActivate: true}
platform-browser.js:380 Router Event: ResolveStart
platform-browser.js:367 ResolveStart(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'view-detail') } )
platform-browser.js:367 ResolveStart {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ResolveEnd
platform-browser.js:367 ResolveEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'view-detail') } )
platform-browser.js:367 ResolveEnd {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: 'view-detail')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: NavigationEnd
platform-browser.js:367 NavigationEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail')
platform-browser.js:367 NavigationEnd {id: 2, url: "/view-detail", urlAfterRedirects: "/view-detail"}

When it doesn't work:

Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 2, url: '/view-detail')
platform-browser.js:367 NavigationStart {id: 2, url: "/view-detail"}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'**') } )
platform-browser.js:367 RoutesRecognized {id: 2, url: "/view-detail", urlAfterRedirects: "/view-detail", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: GuardsCheckStart
platform-browser.js:367 GuardsCheckStart(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'**') } )
platform-browser.js:367 GuardsCheckStart {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: '**')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: GuardsCheckEnd
platform-browser.js:367 GuardsCheckEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'**') } , shouldActivate: true)
platform-browser.js:367 GuardsCheckEnd {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, shouldActivate: true}
platform-browser.js:380 Router Event: ResolveStart
platform-browser.js:367 ResolveStart(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'**') } )
platform-browser.js:367 ResolveStart {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ResolveEnd
platform-browser.js:367 ResolveEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail', state: Route(url:'', path:'') { Route(url:'view-detail', path:'**') } )
platform-browser.js:367 ResolveEnd {id: 2, url: "/view-detail", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: '**')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: NavigationEnd
platform-browser.js:367 NavigationEnd(id: 2, url: '/view-detail', urlAfterRedirects: '/view-detail')
platform-browser.js:367 NavigationEnd {id: 2, url: "/view-detail", urlAfterRedirects: "/view-detail"}

So it seems to be picking up the "**" path instead of the "view-detail" path. Any clue what I'm doing wrong?

* EDIT * App module added:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { CompAModule } from './modules/comp-a/comp-a.module';
import { ViewContainerComponent } from './view-container/view-container.component';
import { CompADetailComponent } from './modules/comp-a-detail/comp-a-detail.component';
import { MyRoutingModule } from './modules/my-module/my-routing.module';


@NgModule({
  declarations: [
    AppComponent,
    ViewContainerComponent,
    CompADetailComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    MyRoutingModule,
    CompAModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
0

1 Answer 1

8

The imports array here:

  imports: [
    BrowserModule,
    AppRoutingModule,
    MyRoutingModule,
    CompAModule
  ],

Defines the ordering of your routes. So as you have it here, Angular will merge your routes together in the following order.

  { path: '', pathMatch: 'full', redirectTo: 'view-container' },
  { path: 'view-container', component: ViewContainerComponent },
  { path:  '**', component: ViewContainerComponent }
  { path: 'view-detail', component: CompADetailComponent }

Since Angular processes routes "first match wins" ... it will always find your '**' route before your 'view-detail' route.

You just need to swap the order in the imports array:

  imports: [
    BrowserModule,
    MyRoutingModule,
    CompAModule,
    AppRoutingModule
  ],

I have a blog post that walks through the details (and exceptions) to the route ordering rules here: https://blogs.msmvps.com/deborahk/angular-route-ordering/

Sign up to request clarification or add additional context in comments.

2 Comments

I just always assumed that these arrays were not ordered. What you said fixed it, thanks!
genius ! thanks. I personnally defined my custom modules right but the original app-routing was indeed at the beginning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.