Angular sub-navigation based on route

Issue

I’m building an Angular application with two levels of navigation in the header.

The top-level navigation are visible on all routes in the application, however the second-level navigation is context-specific and only exists on certain routes.

For example, when viewing a specific course in a university webapp, the second-level navigation might have links to description, prerequisites, the different subjects, etc.

One way of doing it is creating a subnav component that has a switch statement and renders the correct subnav component based on the route:

<div [ngSwitch]="currentRoute">
  <course-sub-nav *ngSwitchCase="course"></course-sub-nav>
  <students-sub-nav *ngSwitchCase="students">...</students-sub-nav>
  <support-sub-nav *ngSwitchCase="support">...</support-sub-nave>
</div>

I don’t like that solution because now the sub-nav component knows too much about all the different context-specific sub-navs.

Another approach is to use a service to manage it. i.e. having a SubNavService.setNavigationLinks(links: NavLink[]) that takes an array of links. The sub-nav component can then listen to changes to the SubNavService and dynamically render a list of sublinks.

This solution is a bit cleaner however it does mean that I need to call that service on ever top-level component to ensure that the sub-nav is being updated. I’d also need to clear the links on pages that don’t require sub-navs.

A third solution might be doing something like:

<!-- In header.component.html -->
<div class="sub-nav">
  <ng-content="subnav"></ng-content>
</div>

<!-- IN course-page.component.html -->
<div>
  <subnav>
    <!-- my nav links -->
  </subnav>

  <div class="course-content">
    <router-outlet></router-outlet>
  </div>
</div>

I like this approach the most given that if a subnav component exists, the subnav will be rendered, and if not, nothing will show. Additionally, the relevant component has full control over rendering the links within the subnav. however given that course-page isn’t actually a child of the header, I’m not sure how I can make it work.

I was wondering if there’s any way to get the last approach to work. If not, would the second approach be the most pragmatic solution to this problem or is there a cleaner solution that exists?

Solution

The cleanest solution would be the second you mentioned.

Having a service that would handle the menu – menu component would subscribe and listen for changes, meanwhile other components would handle what items they need to have in the menu.

Answered By – Tomáš Šedivý

Answer Checked By – Candace Johnson (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.