Katie
Katie

Reputation: 48218

Angular: how to create navigation menu where active class gets toggled on click?

I've created an AngularJS navigation menu and I'm trying to highlight the active menu item based on ng-repeat.

So far I have the menu working with ng-repeat, but I don't know what to put in the ng-click function for the active class to get applied.

Here's what I have:

Here is my view:

//View (in jade):
ul(ng-controller='MenuCtrl')
    li(ng-repeat='navLink in navLinks', ng-click='select(navLink)', ng-class='{active: navLink.linkhref == path}')
        a(href='{{navLink.linkhref}}') {{navLink.linktext}}

And here is my controller:

//Controller:
...
  controller('MenuCtrl', function ($scope,$location) {
    $scope.navLinks = [{
        linkhref: '/',
        linktext: 'View Dashboard',
    }, {
        linkhref: '/rpm',
        linktext: 'View RPMs',
    }, {
        linkhref: '/status',
        linktext: 'View Status',
    }, {
        linkhref: '/database',
        linktext: 'View Database',
    }, {
        linkhref: '/config',
        linktext: 'View Configurations',
    }];

    $scope.path = $location.path();

    $scope.select = function(navLink) {
        //idk what to put here to make the "active" class toggle between nav links
        //I could try this: 
        //remove "active" class from nav links
        //then add "active" class to this link
    };
  })
...

Here's a fiddle with my code:

http://jsfiddle.net/bATZ5/1/

So far here is the behavior:

Resources that were helpful:

Upvotes: 2

Views: 1661

Answers (1)

DRobinson
DRobinson

Reputation: 4471

On your list elements, the ngClick directive is comparing the scope's path value with the navLink element's linkhref value. So if you want the item to gain the class, simply set the values:

$scope.select = function(navLink) {
    $scope.path = navLink.linkhref;
}

While this solves your problem, I believe there's a larger issue with this approach to a menu. Clicking the li element outside of the link will cause the item to appear active. Also, navigating with the keyboard (or in any way that doesn't trigger ngClick) will not update the menu.

Instead of binding the click, it might be worth exploring a method that watches the route:

function updateActiveLink(){
    $scope.path = $location.path();
}
$scope.$on('$routeChangeSuccess', updateActiveLink);

Or another option that I don't like as much:

$scope.$watch(function(){ 
    return $location.path();
}, updateActiveLink);

Upvotes: 2

Related Questions