100

I'm looking for a solution with Angular 2 for the scenario explained below:

enter image description here

In this scenario, the top-nav contains links to load submodules and sub-nav has links to update the submodule's contents.

The URLs should map as:

  • /home => loads the home page in main component router outlet
  • /submodule => loads the submodule in the main component router outlet and by default should show the submodule's home page and sub navbar
  • /submodule/feature => loads the feature inside the submodule's router outlet

The app module (and app component) contains a top navbar to navigate to different submodules and the app component template could look like this

<top-navbar></top-navbar> <router-outlet></router-outlet> 

But here is the complexity. I need my submodules to have a similar layout with a second level nav bar and their own router outlet to load their own components.

<sub-navbar></sub-navbar> <router-outlet name='sub'></router-outlet> 

I tried every option and search everywhere but couldn't find a solution to have a default template (like app component) in the sub-module with router outlet and also load the contents of submodule in the inner router outlet without losing the sub-nav.

I would appreciate any input or ideas

4
  • So what exactly is happening with the current setup? Commented Jan 25, 2017 at 17:30
  • 1
    with the current setup I cannot use inner router outlet. The routing loads even submodule components in the main router outlet and all my submodule component templates have to have a the sub-nav included Commented Jan 25, 2017 at 17:49
  • 1
    did you find a solution to nested router-outlet without loosing the sub-navigation? I have landed into a similar issue. Commented Jul 14, 2017 at 2:49
  • 2
    Yea i think i ran into the same, the <sub-navbar> just doesn't display, only whats coming out of the routeroutlet. Commented Jan 25, 2018 at 12:19

4 Answers 4

67

The html page will look like this.

Main Page

<top-navbar></top-navbar> <router-outlet></router-outlet> 

Sub Module Page

<sub-navbar></sub-navbar> <router-outlet name='sub'></router-outlet> 

on clicking navigation in top-nav bar the main route outlet will route respectively.

while clicking on sub-navbar the router-outlet [sub] will route respectively.

HTML is fine, the trick will came at writing app.routing

app.routing.ts

const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'home', component: homeComponent, children: [ { path: 'module1', component: module1Component, children: [ { path: 'submodule11', component: submodule11Component, }, { path: '', redirectTo: 'submodule11', pathMatch: 'full' } ] }, { path: 'module2', component: module2omponent, children: [ { path: 'submodule21', component: submodule21Component, }, { path: '', redirectTo: 'submodule21', pathMatch: 'full' } ] } ] }, { path: 'about', component: aboutComponent } ] 

Hope it will help you.

More details https://angular.io/guide/router

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

7 Comments

Yesh your html str was correct, The main game is with app.routing.ts I had done similar applications two times.
Thanks for the answer. I tried the similar routing but my confusion is where should that submodule router outlet go? on the main module it is clear that the router outlet should be in app.component's template but we don't have same concept of app component for submodules. so where the "sub" router outlet goes?
The router link must be a string if you add '/' in the beginning of the string it will replace the current route if you dont add '/' the route link will add withe the current route. Still you are not clear please create an sample application in some online coding platform and share the link
I'm not completely sure about this, but the nested router-outlet directive does not need to be named. Here is an example: github.com/gothinkster/angular-realworld-example-app/blob/…
actually it seems that the nested router-outletMUST NOT be named. It works for me only if I do not name it.
|
29

Use:

RouterModule.forChild() ... <router-outlet name="sub"></router-outlet> ... [routerLink]="[{ outlets: { sub: [subRouteName] } }]" 

Full example:

HTML

<div class="tabs tinyscroll"> <button *ngFor="let tab of tabs" [routerLink]="[{ outlets: { sub: [tab.name] } }]" routerLinkActive="selected"> <span>{{ tab.label }}</span> </button> </div> <section> <router-outlet name="sub"></router-outlet> </section> 

app.module.ts

imports: [ ... RouterModule.forChild([ { path: 'registers', component: RegistersComponent, children: [ {path: 'vehicles', component: VehiclesComponent, outlet: 'sub'}, {path: 'drivers', component: DriversComponent, outlet: 'sub'}, {path: 'bases', component: BasesComponent, outlet: 'sub'}, {path: 'lines', component: LinesComponent, outlet: 'sub'}, {path: 'users', component: UsersComponent, outlet: 'sub'}, {path: 'config', component: ConfigComponent, outlet: 'sub'}, {path: 'companies', component: CompaniesComponent, outlet: 'sub'} ], canActivate: [AuthGuard] } ]), ... 

3 Comments

Which version onwards this name route is supported. Bcoz I am trying in v6 and its not working.
This does not work in the current version of angular.
Works for me at angular 12
2

you have to mention the outlet name in the routes mention your router outlet name in the routing like this "outlet:'sub"

routes: Routes = [ {path:'', redirectTo: 'login', pathMatch: 'full'}, { path: 'login', component: LoginComponent, }, { path: 'home', component: AppComponent, children: [ {path: 'home/pdf',component: SideMenuPage,outlet:"sub" }, {path:'home/addFileUp',component:SidePageAdd,outlet:"sub"}, ] }, ]; 

1 Comment

this snippet returns an error: "Uncaught ReferenceError: LoginComponent is not defined"
0

Let's say that you have app.component.ts with a <router-outlet></router-outlet>. That outlet will be referring to app.routes.ts for what to load.

export const appRoutes: Route[] = [ { path: '', component: AppComponent, pathMatch: 'full' }, { path: 'backoffice', children: [ ...backofficeRoutes ] }, ]; 

In this example when the url become http:localhost:4200/backoffice the outlet will load those component using backoffice.routes.ts.

Let's now have a new folder for the backoffice stuff and let's add backoffice.routes.ts into it.

export const backofficeRoutes: Route[] = [ { path: '', component: BackofficeWrapperPageComponent, children: [ { path: 'home', children: [ ...homeRoutes ] } ] } ]; 

And then let's add another outlet into the BackofficeWrapperPageComponent:

<app-header></app-header> <div class="content"> <router-outlet></routing-outlet> </div> <app-footer></app-footer> 

The children section of your backoffice.routes.ts will now hit the outlet of the backoffice wrapper page.

Like this you can have as many outlet as you want and you don't have to specify anything anywere. This works with simple routing for standalone components (Angular 14+). If you are using loadChildren: () => import('./modules/.... then make sure that in the Module you have the same structure as for the Backoffice routing.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.