How to set Bootstrap navbar "active" class in Angular 2?
Asked Answered
C

11

80

How can I set Bootstrap navbar "active" class in Angular 2? I only found Angular 1 way.

When I go to About page, add class="active" to About, and remove class="active" on Home.

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

Thanks

Counterintelligence answered 16/2, 2016 at 2:18 Comment(1)
Although it is not exactly what you are looking for, I believe that routerLink automatically sets the class to router-link-active when that link is active. So if its possible in your project, I would use the class .router-link-active in your css.Hartz
M
176

If you use the new 3.0.0. component router ( https://github.com/angular/vladivostok ) you can use the routerLinkActive directive. No further javascript required.

<ul class="nav navbar-nav">
  <li [routerLinkActive]="['active']"> <a [routerLink]="['one']">One</a></li>
  <li [routerLinkActive]="['active']"> <a [routerLink]="['second']">Second</a></li>
</ul>

I used "@angular/router": "^3.0.0-alpha.7"

Movie answered 22/6, 2016 at 19:15 Comment(5)
Any counterpart in Dart?Beanstalk
still getting confused between ="active" (wrong) and ="['active']" (right). ThanksLandwehr
@Landwehr probably for allowing multiple classes/values to be added if the current route is indeed in an active stateBaboon
@Landwehr In addition to n15m0-jk's answer, you can add routerLinkActive="active" for only one class.Atli
This is the perfect angularish 2 way... Thanks!Irmgardirmina
P
72

Bert Deterd's answer is correct, but there's one thing that can be added.

If one route is a substring of another route, you will see something like this happen: 2 active anchors

You can add this to make it match exact routes only:

[routerLinkActiveOptions]="{exact:true}"

Full Example:

<ul class="nav navbar-nav">
  <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}">
    <a [routerLink]="['/']">Home</a>
  </li>
  <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}">
    <a [routerLink]="['/about']">About</a>
  </li>
  <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}">
    <a [routerLink]="['/calendar']">Calendar</a>
  </li>
</ul>
Piling answered 26/8, 2016 at 16:55 Comment(5)
I ran into this with the home route being just the app domain (empty string). It always showed as active.Parthen
I ran into an issue, whereby clicking outside the link (for example in the center of the web) made the li unactive. This was because I had the angular directives in the anchor tag instead of the a tag. In my head this has no difference, but it works in your way, mybae this comment helps somebody else. Thanks!Counterpunch
The perfect answerRickierickman
Your [routerLinkActiveOptions]="{exact:true}" parameter really helps thanks. For those that are interested in what it does it to stops the active class from activating on the ['/'] Home page when the user is on a different page because it matches the path exactly as it is.Sexdecillion
amazing! Thanks!Backswept
T
10

For the latest version of Angular2 RC4 the following simple code works:

      <li [class.active]="router.url==='/about'"><a [routerLink]="['/about']">About</a></li>

Using import {Router} from "@angular/router"; and put the router in the constructor.

Triacid answered 27/7, 2016 at 8:30 Comment(1)
working fine for me (Y) . But i have a doubt that what i will do here incase of drop down menu.. example" <li class="dropdown"><ul> <li><a></li></ul></li>.". what we have to do if this is the scenario ?Regality
F
6

Use the isRouteActive with generate from the Router class.

According to docs:

generate(linkParams: any[]) : Instruction

Generate an Instruction based on the provided Route Link DSL.

and

isRouteActive(instruction: Instruction) : boolean

Given an instruction, returns true if the instruction is currently active, otherwise false.

<li [class.active]="router.isRouteActive(router.generate(['/Home']))">
   <a [routerLink]="['/Home']">Home</a>
</li>
Fosdick answered 16/2, 2016 at 2:39 Comment(3)
In angular2 rc1, this must be changed to something like this: [class.active]="router.urlTree.contains(router.createUrlTree(['Home']))". Also, I'd like to point out that router must be injected into the component like this: constructor(public router: Router)Saying
To check for the root path /, I did router.urlTree._root.children.length == 0. Seems icky, but works.Cairns
Just a note here: if in your component your constructor looks like: constructor (private router:Router), all the above will work but you wont be able to build for production since router has private access.Baboon
R
5

This does the trick (using RC5)

<li [class.active]="homeLink.classList.contains('active')">
    <a #homeLink routerLink="/home" routerLinkActive="active">Home</a>
</li>
Reckless answered 25/8, 2016 at 13:12 Comment(0)
A
3

On RC2 that did not work for me. I ended up using

   <li  (click)="setActive('home')" class="{{getActive('home')}}"> <a [routerLink]="['/FullScreen']">Home</a></li>

and in the code behind tracked it

    currentChoice: string = "home";

   setActive(choice: string): void{
       this.currentChoice = choice;
   }

   getActive(choice: string) : string{
       if(this.currentChoice == choice)
            return "active";
       else
            return "not";

   }
Ajay answered 16/6, 2016 at 15:49 Comment(0)
D
2

In "@angular/router": "^3.3.1", the difference in the previous version is the bracket in the routerLinkActive

[routerLinkActive]="['active']"

In final release, ng2 will complain so just remove the bracket

routerLinkActive="active"
Dafodil answered 31/1, 2017 at 2:52 Comment(0)
S
1

<a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
true}">Bob</a>
Sedulity answered 17/3, 2017 at 5:54 Comment(0)
S
1

In the case of multiple links try this

<ul class="navbar-nav ml-auto"> 
<li class="nav-item " routerLink="" routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}">
<a class="nav-link" routerLink="">Home </a></li>
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" routerLink="/aboutus">About</a></li>
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" routerLink="/gallery">Gallery</a>
 </li>
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" routerLink="/contactus">Contact Us</a>
</li>
</ul>
Stalingrad answered 29/3, 2019 at 9:49 Comment(0)
S
0

The version "@angular/router": "^3.3.1"

I simply put the name of the route, that I declare in my app.route.ts

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule }   from '@angular/router';

import { HomeComponent } from './home/home.component';
import { DeclarationsComponent } from './declarations/declarations.component';

const appRoutes: Routes = [
    { path: '', pathMatch: 'full', component: HomeComponent },
    { path: 'declarations', pathMatch: 'full', component: DeclarationsComponent }
];

export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

And in the view, I just write the name of the route

  <ul class="nav navbar-nav">
     <li routerLinkActive="active"><a routerLink="">Home</a></li>
     <li><a routerLink="declarations">SAV</a></li>
  </ul>
Scold answered 27/1, 2017 at 16:26 Comment(0)
S
0
import { Directive, HostListener, ElementRef, HostBinding, Renderer2 } from '@angular/core';

@Directive({
  selector: '[appNavDropdown]'
})
export class NavDropdownDirective {
  isOpen:boolean =false;
  counter:number = 0;
  constructor(private el: ElementRef, private render: Renderer2) { }

  @HostBinding('class.open') get opened() {
    return this.isOpen;
  }

  @HostListener('click') onmouseClick()
  {
    this.counter++
    console.log();
    if(this.counter % 2 == 1)//odd
    {
      let part = this.render.parentNode(this.el.nativeElement);
      this.render.addClass(part,'open');
      this.isOpen = true;
    }else{
      let part = this.render.parentNode(this.el.nativeElement);
      this.render.removeClass(part,'open');
      this.isOpen = false;
    }
  }
  // @HostListener('mouseleave') onmouseLeave()
  // {
  //   let part = this.render.parentNode(this.el.nativeElement);
  //   this.render.removeClass(part,'open');
  //   this.isOpen = false;
  // }

  toggleClose() {
    // let part = this.render.parentNode(this.el.nativeElement)
    //this.menuclick = false;

  }
  toggle() {
    this.el.nativeElement.classList.toggle('open');
  }
}

/**
* Allows the dropdown to be toggled via click.
*/
@Directive({
  selector: '[appNavDropdownToggle]'
})
export class NavDropdownToggleDirective {
  constructor(private dropdown: NavDropdownDirective) { }

  @HostListener('click', ['$event'])
  toggleOpen($event: any) {
    console.log($event)
    $event.preventDefault();
  //  this.dropdown.toggleClose()
   this.dropdown.toggle();
  }
}

export const NAV_DROPDOWN_DIRECTIVES = [NavDropdownDirective, NavDropdownToggleDirective];
Safeconduct answered 17/2, 2018 at 6:2 Comment(1)
Please consider adding some explanation.Catchpenny

© 2022 - 2024 — McMap. All rights reserved.