dcp3450
dcp3450

Reputation: 11187

Angular routerLinkActive is matching exact route

Running Angular 8. My main navigation has a set of links one being, for example /services. On that page are services. When a user clicks "Production" it goes to the url /services/production however, the "Services" nav item loses it's active state.

I've applied [routerLinkActiveOptions]="{exact: false}" to attempt enforce the active classes on non-exact routes but it's not maintaining the active state.

the routes for these are in their individual directories so "services" has a services-routing.module that handles it's routing. However the navigation links are the root/app level.

I think I need load those routes into the app-routing.module but not sure how to go about that, if that's the case.

When attempting to lazy load the routes I get the error:

Error: BrowserModule has already been loaded. If you need access to common directives such as NgIf and NgFor from a lazy loaded module, import CommonModule instead.

I double checked and made sure I'm only importing BrowserModule and BrowserAnimationsModule at the app.module level.

--- edit

I have the routes lazy loading but that didn't resolve it. /services shows active but /services/production doesn't

--- edit

app-routing.module:

const routes: Routes = [
  { path: 'logout', component: LogoutComponent },
  { path: 'access-denied', component: AccessDeinedComponent }
];

app.component

this.navLinks = [
  { path: '/about', label: 'About', icon: 'assessment' },
  { path: '/contact', label: 'Contact', icon: 'assignment' },
  { path: '/services', label: 'Services', icon: 'settings' }
];

app.component.html

  <nav class="nav-tab-group" mat-tab-nav-bar color="accent">
        <a mat-tab-link *ngFor="let link of navLinks"
        [routerLink]="link.path"
        routerLinkActive="mat-tab-label-active active-link"
        class="subnav-link">
        <mat-icon class="tab-icon">{{link.icon}} is view</mat-icon>
        <span class="link-text" >{{link.label}}</span>
    </a>
  </nav>

services-routing.module (in a different directory)

const routes: Routes = [
  {
    path: '',
    component: ServicesComponent,
    canActivate: [AuthGuardService],
    data: { roles },
    children: [
      {
        path: 'services/production',
        component: ProductionComponent,
        canActivate: [AuthGuardService],
        data: { roles }
      }...
    ]
  }
];

So the actual route behavior in in the services-routing.module and the nav in in the root app.component scripts. When I"m at the services root, the services routerLink is active but all children it's inactive.

Upvotes: 2

Views: 3209

Answers (1)

dcp3450
dcp3450

Reputation: 11187

The solution I've landed on is adding my active link class conditionally:

[ngClass]="{'active-link': setActiveNav(link)}"

my navLinks variable has an addition string[] that hold other acceptable paths, for example ['/services/production'].

The method that returns true looks for the existence of additional paths and check if it exists in location.path() using the Location class from @angular/common. It also checks against the expected path.

I also have an situation where a nav item needs to be "active" on a completely unrelated URL.

  setActiveNav(navLink): boolean {
    const currentPath = this.location.path();
    let foundPath = false;
    if (navLink.additionalPaths) {
      navLink.additionalPaths.forEach(path => {
        if (currentPath.indexOf(path) >= 0 || currentPath.indexOf(navLink.path) >= 0) {
          foundPath = true;
        }
      });
    } else if (currentPath.indexOf(navLink.path) >= 0) {
      foundPath = true;
    }

    return foundPath;
  }

Upvotes: 1

Related Questions