How to set bootstrap navbar active class with Angular JS?
A very elegant way is to use ng-controller to run a single controller outside of the ng-view:
<div class="collapse navbar-collapse" ng-controller="HeaderController"> <ul class="nav navbar-nav"> <li ng-class="{ active: isActive('/')}"><a href="/">Home</a></li> <li ng-class="{ active: isActive('/dogs')}"><a href="/dogs">Dogs</a></li> <li ng-class="{ active: isActive('/cats')}"><a href="/cats">Cats</a></li> </ul></div><div ng-view></div>
and include in controllers.js:
function HeaderController($scope, $location) { $scope.isActive = function (viewLocation) { return viewLocation === $location.path(); };}
I just wrote a directive to handle this, so you can simply add the attribute bs-active-link
to the parent <ul>
element, and any time the route changed, it will find the matching link, and add the active
class to the corresponding <li>
.
You can see it in action here: http://jsfiddle.net/8mcedv3b/
Example HTML:
<ul class="nav navbar-nav" bs-active-link> <li><a href="/home">Home</a></li> <li><a href="/contact">Contact</a></li></ul>
Javascript:
angular.module('appName').directive('bsActiveLink', ['$location', function ($location) {return { restrict: 'A', //use as attribute replace: false, link: function (scope, elem) { //after the route has changed scope.$on("$routeChangeSuccess", function () { var hrefs = ['/#' + $location.path(), '#' + $location.path(), //html5: false $location.path()]; //html5: true angular.forEach(elem.find('a'), function (a) { a = angular.element(a); if (-1 !== hrefs.indexOf(a.attr('href'))) { a.parent().addClass('active'); } else { a.parent().removeClass('active'); }; }); }); }}}]);
You can have a look at AngularStrap, the navbar directive seems to be what you are looking for:
https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js
.directive('bsNavbar', function($location) { 'use strict'; return { restrict: 'A', link: function postLink(scope, element, attrs, controller) { // Watch for the $location scope.$watch(function() { return $location.path(); }, function(newValue, oldValue) { $('li[data-match-route]', element).each(function(k, li) { var $li = angular.element(li), // data('match-rout') does not work with dynamic attributes pattern = $li.attr('data-match-route'), regexp = new RegExp('^' + pattern + '$', ['i']); if(regexp.test(newValue)) { $li.addClass('active'); } else { $li.removeClass('active'); } }); }); } };});
To use this directive:
Download AngularStrap from http://mgcrea.github.io/angular-strap/
Include the script on your page after bootstrap.js:
<script src="lib/angular-strap.js"></script>
Add the directives to your module:
angular.module('myApp', ['$strap.directives'])
Add the directive to your navbar:
<div class="navbar" bs-navbar>
Add regexes on each nav item:
<li data-match-route="/about"><a href="#/about">About</a></li>