Matthias
Matthias

Reputation: 1032

How to define routes for named router outlets which are in a sub component

I would like to build an angular 4 app that consists of like two different sub-apps: main-app and admin-app. I was thinking about having an app component which is bootstrapped and has only the <router-outlet> in the template:

app.component
template: <router-outlet></router-outlet>
routes:
"main" => main-app
"admin" => admin-app

The main-app has a router-outlet and a named router-outlet in the template where I would like to display different components at the same time.
main-app.component
template: <router-outlet></router-outlet><router-outlet name='action'></router-outlet>
routes:
"content" => content.component
"action" => action.component (displayed in the action router-outlet)

My problem is that the "action" route does not work, i.e. it does not display the action.component in the action router-outlet when accessing http://localhost:4200/main/app(action:action) or http://localhost:4200/main/app/content(action:action), but gives an exception:

Error: Cannot match any routes. URL Segment: 'action'

My actual routes look like this:
app-routing.module

const routes: Routes = [
  {
    path: 'main',
    loadChildren: "app/main-app/main-app.module#MainAppModule",
  },
  {
    path: 'admin',
    loadChildren: "app/admin-app/admin-app.module#AdminAppModule",
  },
]

main-app-routing.module

const routes: Routes = [
  {
    path: "",
    redirectTo: "app",
    pathMatch: "full"
  },
  {
    path: "app",
    component: MainAppComponent,
    children: [
      {
        path: "content",
        component: ContentComponent
      },
      {
        path: "action",
        outlet: "action",
        component: ActionComponent
      }
    ]
  }
]

My questions:
How do I have to specify the routes in order to make it work?
Is there another recommended way to have build my app that consists of two sub-apps?

Thank you!

Upvotes: 3

Views: 1439

Answers (2)

Matthias
Matthias

Reputation: 1032

I figured out how it could be achieved:

By using the URL:
http://localhost:4200/main/app/(content//action:action)
it works!

And the routerLink has to look like this:
<a [routerLink]="['/main/app', { outlets: { primary: 'content', action: 'action' } }]" >content & action</a>

This is the main-app.component.html:

<span><a [routerLink]="['/main/app', { outlets: { primary: 'content', action: null } }]" >content only</a></span>
<span><a [routerLink]="['/main/app', { outlets: { primary: null, action: 'action' } }]" >action only</a></span>
<span><a [routerLink]="['/main/app', { outlets: { primary: 'content', action: 'action' } }]" >content & action</a></span>

<div>primary:</div>
<div><router-outlet></router-outlet></div>

<div>action:</div>
<div><router-outlet name="action"></router-outlet></div>

Maybe someone knows another/better solution?

Upvotes: 0

bgraham
bgraham

Reputation: 2027

Instead of having a named router-outlet I would actually have nested routing components. So your main AppComponent just has one router-outlet. And your routing for your app is fine the way you have it:

const routes: Routes = [
  {
    path: 'main',
    loadChildren: "app/main-app/main-app.module#MainAppModule",
  },
  {
    path: 'admin',
    loadChildren: "app/admin-app/admin-app.module#AdminAppModule",
  },
]

But now you create two separate modules for the two sub apps. The MainApp for example would look like this:

const mainAppRoutes: Routes = [
  {
    path: 'main',
    component: MainAppComponent,
    children: [
      {
        path: "content",
        component: ContentComponent
      },
      {
        path: "action",
        outlet: "action",
        component: ActionComponent
      }
    ]
  }


@NgModule({
  imports: [
    RouterModule.forChild(mainAppRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class MainAppModule { }


@Component({
  template:  `
    <h2>Main App</h2>
    <router-outlet></router-outlet>
  `
})
export class MainAppComponent { }

Notice that the routes have a nested children routes array. These routes will actually get plugged into the MainAppComponent router-outlet not into the AppComponent router-outlet. Then you can import those routes into the MainAppModule using the RouterModule.forChild() method. This set up will still work with our lazy loading, and I think will give you a cleaner separation in your areas.

Upvotes: 0

Related Questions