Getting the Bootstrap 3 Navbar and AngularJS to play nicely together
I ran into a couple of issues when using the Bootstrap 3 Navbar component in an AngularJS application, namely:
- The navbar doesn't collapse automatically when the route / location is changed (applies to 'mobile' view only)
- The active menu item isn't tracked correctly, it just stays the same when the location is changed
Here's how to fix them:
Collapse Bootstrap 3 Navbar on route / location change
In the HTML
Find this line:
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
And change it to:
<button type="button" class="navbar-toggle" ng-click="isCollapsed = !isCollapsed">
Then find this line:
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
And change it to:
<div class="navbar-collapse" ng-class="isCollapsed ? 'collapse' : 'in'">
Add the attribute ng-controller="NavController" to your <nav> element to hook up the Navbar to your AngularJS controller:
<nav ng-controller="NavController" class="navbar navbar-default navbar-fixed-top" role="navigation">
In the Controller
Initialise the isCollapsed variable on the $scope to true, and add an event handler on route change to reset it to true:
var app = angular.module('myapp.controllers', []); app.controller('NavController', function ($scope, $location) { $scope.isCollapsed = true; $scope.$on('$routeChangeSuccess', function () { $scope.isCollapsed = true; }); });
Correctly keep track of active menu item
In the HTML
Add the attribute ng-class="getClass('[PATH]')" to each of your menu item <li> elements, eg:
<li ng-class="getClass('/')"><a href="#/">Home</a></li> <li ng-class="getClass('/page1')"><a href="#/page1">Page 1</a></li>
In the Controller
Add the getClass function to the $scope, which will compare the path argument to the current location and return 'active' for the current menu item:
$scope.getClass = function (path) { if(path === '/') { if($location.path() === '/') { return "active"; } else { return ""; } } if ($location.path().substr(0, path.length) === path) { return "active"; } else { return ""; } }
Note: Because this approach uses the AngularJS framework to do everything, you don't need to include the bootstrap js file in your code.