In Angular, how do you determine the active route?

JavascriptTypescriptAngularAngular2 Routing

Javascript Problem Overview


NOTE: There are many different answers here, and most have been valid at one time or another. The fact is that what works has changed a number of times as the Angular team has changed its Router. The Router 3.0 version that will eventually be the router in Angular breaks many of these solutions, but offers a very simple solution of its own. As of RC.3, the preferred solution is to use [routerLinkActive] as shown in this answer.

In an Angular application (current in the 2.0.0-beta.0 release as I write this), how do you determine what the currently active route is?

I'm working on an app that uses Bootstrap 4 and I need a way to mark navigation links/buttons as active when their associated component is being shown in a <router-output> tag.

I realize that I could maintain the state myself when one of the buttons is clicked upon, but that wouldn't cover the case of having multiple paths into the same route (say a main navigation menu as well as a local menu in the main component).

Any suggestions or links would be appreciated. Thanks.

Javascript Solutions


Solution 1 - Javascript

With the new Angular router, you can add a [routerLinkActive]="['your-class-name']" attribute to all your links:

<a [routerLink]="['/home']" [routerLinkActive]="['is-active']">Home</a>

Or the simplified non-array format if only one class is needed:

<a [routerLink]="['/home']" [routerLinkActive]="'is-active'">Home</a>

Or an even simpler format if only one class is needed:

<a [routerLink]="['/home']" routerLinkActive="is-active">Home</a>

See the poorly documented routerLinkActive directive for more info. (I mostly figured this out via trial-and-error.)

UPDATE: Better documentation for the routerLinkActive directive can now be found here. (Thanks to @Victor Hugo Arango A. in the comments below.)

Solution 2 - Javascript

I've replied this in another question but I believe it might be relevant to this one as well. Here's a link to the original answer: https://stackoverflow.com/questions/34571517/angular-2-how-to-determine-active-route-with-parameters/34571947#34571947

I've been trying to set the active class without having to know exactly what's the current location (using the route name). The is the best solution I have got to so far is using the function isRouteActive available in the Router class.

router.isRouteActive(instruction): Boolean takes one parameter which is a route Instruction object and returns true or false whether that instruction holds true or not for the current route. You can generate a route Instruction by using Router's generate(linkParams: Array). LinkParams follows the exact same format as a value passed into a routerLink directive (e.g. router.isRouteActive(router.generate(['/User', { user: user.id }])) ).

This is how the RouteConfig could look like (I've tweaked it a bit to show the usage of params):

@RouteConfig([
  { path: '/', component: HomePage, name: 'Home' },
  { path: '/signin', component: SignInPage, name: 'SignIn' },
  { path: '/profile/:username/feed', component: FeedPage, name: 'ProfileFeed' },
])

And the View would look like this:

<li [class.active]="router.isRouteActive(router.generate(['/Home']))">
   <a [routerLink]="['/Home']">Home</a>
</li>
<li [class.active]="router.isRouteActive(router.generate(['/SignIn']))">
   <a [routerLink]="['/SignIn']">Sign In</a>
</li>
<li [class.active]="router.isRouteActive(router.generate(['/ProfileFeed', { username: user.username }]))">
    <a [routerLink]="['/ProfileFeed', { username: user.username }]">Feed</a>
</li>

This has been my preferred solution for the problem so far, it might be helpful for you as well.

Solution 3 - Javascript

Small improvement to @alex-correia-santos answer based on https://github.com/angular/angular/pull/6407#issuecomment-190179875

import {Router, RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
// ...
export class App {
  constructor(private router: Router) {
  }

  // ...

  isActive(instruction: any[]): boolean {
    return this.router.isRouteActive(this.router.generate(instruction));
  }
} 

And use it like this:

<ul class="nav navbar-nav">
	<li [class.active]="isActive(['Home'])">
		<a [routerLink]="['Home']">Home</a>
	</li>
	<li [class.active]="isActive(['About'])">
		<a [routerLink]="['About']">About</a>
	</li>
</ul>

Solution 4 - Javascript

I solved a problem I encountered in this link and I find out that there is a simple solution for your question. You could use router-link-active instead in your styles.

@Component({
   styles: [`.router-link-active { background-color: red; }`]
})
export class NavComponent {
}

Solution 5 - Javascript

You can check the current route by injecting the Location object into your controller and checking the path(), like so:

class MyController {
    constructor(private location:Location) {}

    ...  location.path(); ...
}

You will have to make sure to import it first:

import {Location} from "angular2/router";

You can then use a regular expression to match against the path that's returned to see which route is active. Note that the Location class returns a normalized path regardless of which LocationStrategy you're using. So even if you're using the HashLocationStragegy the paths returned will still be of the form /foo/bar not #/foo/bar

Solution 6 - Javascript

> how do you determine what the currently active route is?

UPDATE: updated as per Angular2.4.x

constructor(route: ActivatedRoute) {
   route.snapshot.params; // active route's params

   route.snapshot.data; // active route's resolved data

   route.snapshot.component; // active route's component

   route.snapshot.queryParams // The query parameters shared by all the routes
}

see more...

Solution 7 - Javascript

To mark active routes routerLinkActive can be used

<a [routerLink]="/user" routerLinkActive="some class list">User</a>

This also works on other elements like

<div routerLinkActive="some class list">
  <a [routerLink]="/user">User</a>
</div>

If partial matches should also be marked use

routerLinkActive="some class list" [routerLinkActiveOptions]="{ exact: false }"

As far as I know exact: false is going to be the default in RC.4

Solution 8 - Javascript

Right now i'm using rc.4 with bootstrap 4 and this one works perfect for me:

 <li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact:
true}">
    <a class="nav-link" [routerLink]="['']">Home</a>
</li>

This will work for url : /home

Solution 9 - Javascript

in 2020 if you want to set active class on element which has no [routerLink] - you can do simply:

<a
  (click)="bookmarks()"
  [class.active]="router.isActive('/string/path/'+you+'/need', false)" // <== you need this one. second argument 'false' - exact: true/false
  routerLinkActive="active"
  [routerLinkActiveOptions]="{ exact: true }"
>
  bookmarks
</a>

Solution 10 - Javascript

As of Angular 8, this works:

<li routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
    <a [routerLink]="['/']">Home</a>
</li>

{ exact: true } ensures it matches the url.

Solution 11 - Javascript

Just thought I would add in an example which doesn't use any typescript:

<input type="hidden" [routerLink]="'home'" routerLinkActive #home="routerLinkActive" />
<section *ngIf="home.isActive"></section>

The routerLinkActive variable is bound to a template variable and then re-used as required. Unfortunately the only caveat is that you can't have this all on the <section> element as #home needs to be resolved prior to the parser hitting <section>.

Solution 12 - Javascript

Below is the method using RouteData to style menuBar items depending of the current route:

RouteConfig includes data with tab (current route):

@RouteConfig([
  {
    path: '/home',    name: 'Home',    component: HomeComponent,
    data: {activeTab: 'home'},  useAsDefault: true
  }, {
    path: '/jobs',    name: 'Jobs',    data: {activeTab: 'jobs'},
    component: JobsComponent
  }
])

A piece of layout:

  <li role="presentation" [ngClass]="{active: isActive('home')}">
    <a [routerLink]="['Home']">Home</a>
  </li>
  <li role="presentation" [ngClass]="{active: isActive('jobs')}">
    <a [routerLink]="['Jobs']">Jobs</a>
  </li>

Class:

export class MainMenuComponent {
  router: Router;

  constructor(data: Router) {
    this.router = data;
  }

  isActive(tab): boolean {
    if (this.router.currentInstruction && this.router.currentInstruction.component.routeData) {
      return tab == this.router.currentInstruction.component.routeData.data['activeTab'];
    }
    return false;
  }
}

Solution 13 - Javascript

Router in Angular 2 RC no longer defines isRouteActive and generate methods.

> urlTree - Returns the current url tree. > > createUrlTree(commands: any[], segment?: RouteSegment) - Applies an array of commands to the current url tree and creates a new url tree. >

Try following

<li 
[class.active]=
"router.urlTree.contains(router.createUrlTree(['/SignIn', this.routeSegment]))">

notice, routeSegment : RouteSegment must be injected into component's constructor.

Solution 14 - Javascript

Here's a complete example for adding active route styling in Angular version 2.0.0-rc.1 which takes into account null root paths (e.g. path: '/')

app.component.ts -> Routes

import { Component, OnInit } from '@angular/core';
import { Routes, Router, ROUTER_DIRECTIVES } from '@angular/router';
import { LoginPage, AddCandidatePage } from './export';
import {UserService} from './SERVICES/user.service';

@Component({
  moduleId: 'app/',
  selector: 'my-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  providers: [UserService],
  directives: [ROUTER_DIRECTIVES]
})

@Routes([
  { path: '/', component: AddCandidatePage },
  { path: 'Login', component: LoginPage }
])
export class AppComponent  { //implements OnInit
  
  constructor(private router: Router){}

  routeIsActive(routePath: string) {
     let currentRoute = this.router.urlTree.firstChild(this.router.urlTree.root);
     // e.g. 'Login' or null if route is '/'
     let segment = currentRoute == null ? '/' : currentRoute.segment;
     return  segment == routePath;
  }
}

app.component.html

<ul>
  <li [class.active]="routeIsActive('Login')"><a [routerLink]="['Login']" >Login</a></li>
  <li [class.active]="routeIsActive('/')"><a [routerLink]="['/']" >AddCandidate</a></li>
</ul>
<route-outlet></router-outlet>

Solution 15 - Javascript

Solution for Angular2 RC 4:

import {containsTree} from '@angular/router/src/url_tree';
import {Router} from '@angular/router';

export function isRouteActive(router: Router, route: string) {
   const currentUrlTree = router.parseUrl(router.url);
   const routeUrlTree = router.createUrlTree([route]);
   return containsTree(currentUrlTree, routeUrlTree, true);
}

Solution 16 - Javascript

Using routerLinkActive is good in simple cases, when there is a link and you want to apply some classes. But in more complex cases where you may not have a routerLink or where you need something more you can create and use a pipe:

@Pipe({
    name: "isRouteActive",
    pure: false
})
export class IsRouteActivePipe implements PipeTransform {

    constructor(private router: Router,
                private activatedRoute: ActivatedRoute) {
    }

    transform(route: any[], options?: { queryParams?: any[], fragment?: any, exact?: boolean }) {
        if (!options) options = {};
        if (options.exact === undefined) options.exact = true;

        const currentUrlTree = this.router.parseUrl(this.router.url);
        const urlTree = this.router.createUrlTree(route, {
            relativeTo: this.activatedRoute,
            queryParams: options.queryParams,
            fragment: options.fragment
        });
        return containsTree(currentUrlTree, urlTree, options.exact);
    }
}

then:

<div *ngIf="['/some-route'] | isRouteActive">...</div>

and don't forget to include pipe in the pipes dependencies ;)

Solution 17 - Javascript

Another Workaround. Much easier in Angular Router V3 Alpha. by injecting Router

import {Router} from "@angular/router";

export class AppComponent{

    constructor(private router : Router){}

	routeIsActive(routePath: string) {
        return this.router.url == routePath;
    }
}

usage

<div *ngIf="routeIsActive('/')"> My content </div>

Solution 18 - Javascript

In Angular2 RC2 you can use this simple implementation

<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>

this will add class active to the element with matched url, read more about it here

Solution 19 - Javascript

Below are the answers to this question for all the versions of Angular 2 RC versions released till date:

RC4 and RC3 :

For applying class to link or ancestor of link :

<li routerLinkActive="active"><a [routerLink]="['/home']">Home</a></li>

/home should be the URL and not the name of route since name property no longer exists on Route Object as of Router v3.

More about routerLinkActive directive at this link.

For applying class to any div based on current route :

  • Inject Router into constructor of component.
  • User router.url for comparison.

e.g

<nav [class.transparent]="router.url==('/home')">
</nav>

RC2 and RC1:

Use combination of router.isRouteActive and class.*. e.g to apply active class based on Home Route.

Name and url can both be passed into router.generate.

 <li [class.active]="router.isRouteActive(router.generate(['Home']))">
    <a [routerLink]="['Home']" >Home</a>
</li>

Solution 20 - Javascript

For Angular version 4+, you don't need to use any complex solution. You can simply use [routerLinkActive]="'is-active'".

For an example with bootstrap 4 nav link:

    <ul class="navbar-nav mr-auto">
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/home">Home</a>
      </li>
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/about-us">About Us</a>
      </li>
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link " routerLink="/contact-us">Contact</a>
      </li>
    </ul>

Solution 21 - Javascript

And in the latest version of angular, you can simply do check router.isActive(routeNameAsString). For example see the example below:

 <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav">
      <li class="nav-item" [class.active] = "router.isActive('/dashboard')">
        <a class="nav-link" href="#">داشبورد <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item" [class.active] = "router.isActive(route.path)" *ngFor="let route of (routes$ | async)">
        <a class="nav-link" href="javascript:void(0)" *ngIf="route.childRoutes && route.childRoutes.length > 0"
          [matMenuTriggerFor]="menu">{{route.name}}</a>
        <a class="nav-link" href="{{route.path}}"
          *ngIf="!route.childRoutes || route.childRoutes.length === 0">{{route.name}}</a>
        <mat-menu #menu="matMenu">
          <span *ngIf="route.childRoutes && route.childRoutes.length > 0">
            <a *ngFor="let child of route.childRoutes" class="nav-link" href="{{route.path + child.path}}"
              mat-menu-item>{{child.name}}</a>
          </span>
        </mat-menu>
      </li>
    </ul>
    <span class="navbar-text mr-auto">
      <small>سلام</small> {{ (currentUser$ | async) ? (currentUser$ | async).firstName : 'کاربر' }}
      {{ (currentUser$ | async) ? (currentUser$ | async).lastName : 'میهمان' }}
    </span>
  </div>

And make sure you are not forgetting injecting router in your component.

Solution 22 - Javascript

An instance of the Router class is actually an Observable and it returns the current path everytime it changes. This is how I do it :

export class AppComponent implements OnInit { 

currentUrl : string;

constructor(private _router : Router){
    this.currentUrl = ''
}

ngOnInit() {
    this._router.subscribe(
        currentUrl => this.currentUrl = currentUrl,
        error => console.log(error)
    );
}

isCurrentRoute(route : string) : boolean {
    return this.currentUrl === route;
 } 
}

And then in my HTML :

<a [routerLink]="['Contact']" class="item" [class.active]="isCurrentRoute('contact')">Contact</a>

Solution 23 - Javascript

As mentioned in one of the comments of the accepted answer, the routerLinkActive directive can also be applied to a container of the actual <a> tag.

So for example with Twitter Bootstrap tabs where the active class should be applied to the <li> tag that contains the link :

<ul class="nav nav-tabs">
    <li role="presentation" routerLinkActive="active">
        <a routerLink="./location">Location</a>
    </li>
    <li role="presentation" routerLinkActive="active">
        <a routerLink="./execution">Execution</a>
    </li>
</ul>

Pretty neat ! I suppose the directive inspects the content of the tag and looks for an <a> tag with the routerLink directive.

Solution 24 - Javascript

Simple solution for angular 5 users is, just add routerLinkActive to the list item.

A routerLinkActive directive is associated with a route through a routerLink directive.

It takes as input an array of classes which it will add to the element it’s attached to if it’s route is currently active, like so:

<li class="nav-item"
    [routerLinkActive]="['active']">
  <a class="nav-link"
     [routerLink]="['home']">Home
  </a>
</li>

The above will add a class of active to the anchor tag if we are currently viewing the home route.

Demo

Solution 25 - Javascript

This helped me for active/inactive routes:

<a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive" [ngClass]="rla.isActive ? 'classIfActive' : 'classIfNotActive'">
</a>

Ref

Solution 26 - Javascript

I was seeking a way to use a Twitter Bootstrap style nav with Angular2, but had trouble getting the active class applied to the parent element of the selected link. Found that @alex-correia-santos's solution works perfectly!

The component containing your tabs has to import the router and define it in its constructor before you can make the necessary calls.

Here's a simplified version of my implementation...

import {Component} from 'angular2/core';
import {Router, RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {HomeComponent} from './home.component';
import {LoginComponent} from './login.component';
import {FeedComponent} from './feed.component';

@Component({
  selector: 'my-app',
  template: `
    <ul class="nav nav-tabs">
      <li [class.active]="_r.isRouteActive(_r.generate(['Home']))">
        <a [routerLink]="['Home']">Home</a>
      </li>
      <li [class.active]="_r.isRouteActive(_r.generate(['Login']))">
        <a [routerLink]="['Login']">Sign In</a>
      </li>
      <li [class.active]="_r.isRouteActive(_r.generate(['Feed']))">
        <a [routerLink]="['Feed']">Feed</a>
      </li>
    </ul>`,
  styleUrls: ['app/app.component.css'],
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
  { path:'/', component:HomeComponent, name:'Home', useAsDefault:true },
  { path:'/login', component:LoginComponent, name:'Login' },
  { path:'/feed', component:FeedComponent, name:'Feed' }
])
export class AppComponent {
  title = 'My App';
  constructor( private _r:Router ){}
}

Solution 27 - Javascript

let's say you want to add CSS to my active state/tab. Use routerLinkActive to activate your routing link.

note : 'active' is my class name here

<style>
   .active{
       color:blue;
     }
</style>

  <a routerLink="/home" [routerLinkActive]="['active']">Home</a>
  <a routerLink="/about" [routerLinkActive]="['active']">About</a>
  <a routerLink="/contact" [routerLinkActive]="['active']">Contact</a>

Solution 28 - Javascript

A programatic way would be to do it in the component itself. I struggled three weeks on this issue, but gave up on angular docs and read the actual code that made routerlinkactive work and Thats about the best docs I can find.

    import {
  Component,AfterContentInit,OnDestroy, ViewChild,OnInit, ViewChildren, AfterViewInit, ElementRef, Renderer2, QueryList,NgZone,ApplicationRef
}
  from '@angular/core';
  import { Location } from '@angular/common';

import { Subscription } from 'rxjs';
import {
  ActivatedRoute,ResolveStart,Event, Router,RouterEvent, NavigationEnd, UrlSegment
} from '@angular/router';
import { Observable } from "rxjs";
import * as $ from 'jquery';
import { pairwise, map } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
import {PageHandleService} from '../pageHandling.service'
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})




export class HeaderComponent implements AfterContentInit,AfterViewInit,OnInit,OnDestroy{

    public previousUrl: any;
    private subscription: Subscription;


      @ViewChild("superclass", { static: false } as any) superclass: ElementRef;
      @ViewChildren("megaclass") megaclass: QueryList<ElementRef>;


  constructor( private element: ElementRef, private renderer: Renderer2, private router: Router, private activatedRoute: ActivatedRoute, private location: Location, private pageHandleService: PageHandleService){
    this.subscription = router.events.subscribe((s: Event) => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });


  }


  ngOnInit(){

  }


  ngAfterViewInit() {
  }

  ngAfterContentInit(){
  }



private update(): void {
  if (!this.router.navigated || !this.superclass) return;
      Promise.resolve().then(() => {
        this.previousUrl = this.router.url

        this.megaclass.toArray().forEach( (superclass) => {

          var superclass = superclass
          console.log( superclass.nativeElement.children[0].classList )
          console.log( superclass.nativeElement.children )

          if (this.previousUrl == superclass.nativeElement.getAttribute("routerLink")) {
            this.renderer.addClass(superclass.nativeElement.children[0], "box")
            console.log("add class")

          } else {
            this.renderer.removeClass(superclass.nativeElement.children[0], "box")
            console.log("remove class")
          }

        });
})
//update is done
}
ngOnDestroy(): void { this.subscription.unsubscribe(); }


//class is done
}

Note:
For the programatic way, make sure to add the router-link and it takes a child element. If you want to change that, you need to get rid of the children on superclass.nativeElement.

Solution 29 - Javascript

I'm using angular router ^3.4.7 and I'm still having problems with the routerLinkActive directive.

It's not working if you have multiple link with the same url plus it does not seem to refresh all the time.

Inspired by @tomaszbak answer I created a little component to do the job

Solution 30 - Javascript

Pure html template be like

 <a [routerLink]="['/home']" routerLinkActive="active">Home</a>
 <a [routerLink]="['/about']" routerLinkActive="active">About us</a>
 <a [routerLink]="['/contact']" routerLinkActive="active">Contacts</a>

Solution 31 - Javascript

start with importing RouterLinkActive in your .ts

> import { RouterLinkActive } from '@angular/router';

Now use RouterLinkActive in your HTML

<span class="" routerLink ="/some_path" routerLinkActive="class_Name">Value</span></a>

provide some css to class "class_Name" , as when this link will be active/clicked you will find this class on span while inspection.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael OrylView Question on Stackoverflow
Solution 1 - JavascriptjessepinhoView Answer on Stackoverflow
Solution 2 - JavascriptAlex SantosView Answer on Stackoverflow
Solution 3 - JavascripttomaszbakView Answer on Stackoverflow
Solution 4 - JavascriptQuy TangView Answer on Stackoverflow
Solution 5 - JavascriptJason TeplitzView Answer on Stackoverflow
Solution 6 - JavascriptAnkit SinghView Answer on Stackoverflow
Solution 7 - JavascriptGünter ZöchbauerView Answer on Stackoverflow
Solution 8 - JavascriptArtem ZinovievView Answer on Stackoverflow
Solution 9 - JavascriptKurkov IgorView Answer on Stackoverflow
Solution 10 - JavascriptcodejockieView Answer on Stackoverflow
Solution 11 - JavascriptZzeView Answer on Stackoverflow
Solution 12 - JavascriptIvanView Answer on Stackoverflow
Solution 13 - JavascripttchelidzeView Answer on Stackoverflow
Solution 14 - JavascriptLevi FullerView Answer on Stackoverflow
Solution 15 - JavascriptlukavilleView Answer on Stackoverflow
Solution 16 - JavascriptpleerockView Answer on Stackoverflow
Solution 17 - Javascriptshakee93View Answer on Stackoverflow
Solution 18 - JavascriptKhaled Al-AnsariView Answer on Stackoverflow
Solution 19 - JavascriptInderdeep SinghView Answer on Stackoverflow
Solution 20 - JavascriptasmmahmudView Answer on Stackoverflow
Solution 21 - JavascriptConductedCleverView Answer on Stackoverflow
Solution 22 - JavascriptAnees DhanseyView Answer on Stackoverflow
Solution 23 - JavascriptPierre HenryView Answer on Stackoverflow
Solution 24 - JavascriptPrasanth JayaView Answer on Stackoverflow
Solution 25 - JavascriptMohammad Zaid PathanView Answer on Stackoverflow
Solution 26 - JavascriptBen ThielkerView Answer on Stackoverflow
Solution 27 - JavascriptUniCoderView Answer on Stackoverflow
Solution 28 - JavascriptGrant mitchell soundbreakr1View Answer on Stackoverflow
Solution 29 - JavascriptRPDeshaiesView Answer on Stackoverflow
Solution 30 - JavascriptBellashView Answer on Stackoverflow
Solution 31 - JavascriptT. ShashwatView Answer on Stackoverflow