How to update AngularJS directive when URL is changed?

16,368

Solution 1

Using kfis's code from https://stackoverflow.com/a/12631214/1684860 in the comments, I have this working now using $scope.watch on location.path() .

myModule.directive('highlighttab', ['$location', function(location) {

    return {
        restrict: 'C',
        link: function($scope, $element, $attrs) {
            var elementPath = $attrs.href.substring(1);
            $scope.$location = location;
            $scope.$watch('$location.path()', function(locationPath) {
                (elementPath === locationPath) ? $element.addClass("current") : $element.removeClass("current");
            });
        }
    };
}]);

Solution 2

Assuming you are using ngView/routeProvider you probably need to listen for a route change event, perhaps $routeChangeSuccess 1.

e.g. in your link function:

scope.$on("$routeChangeSuccess", function (event, current, previous) {
    if (current == href) {
      element.addClass("current");
    }
    else {
      element.removeClass("current");
    }
});

Not tested so might need tinkering e.g. for presence/absence of '#'. I expect your currentPath variable is only being evaluated once, so you might want to rework that into the link function so its effective scope is clearer.

1 [http://docs.angularjs.org/api/ng.$route]

Share:
16,368
Michael Low
Author by

Michael Low

Updated on June 09, 2022

Comments

  • Michael Low
    Michael Low almost 2 years

    Possible Duplicate:
    Set active tab style with AngularJS

    I'm using AngularJS and trying to add a "current" class to my menu whenever that tab's content is being displayed. This is what I have so far, and it works fine when loading the page:

    HTML:

    <ul id="nav">
        <li><a href="#/one" class="highlighttab">One</a></li>
        <li><a href="#/two" class="highlighttab">Two</a></li>
    </ul>
    

    JS:

    myModule.directive('highlighttab', function($location) {
        var currentPath = "#" + $location.path();
    
        return {
            restrict: 'C',
            link: function(scope, element, attrs) {
                var href = element.attr("href");
                if (currentPath == href)
                {
                    element.addClass("current");
                }
            }
        };
    });
    

    This will add the 'current' class to the correct <a> tag when the page url is #/one or /#two

    The problem is if I click the second tab, the class does not get added to it. I imagine I need some way to get the code inside the directive to be re-run when the URL changes. Is there any way to do that ?

    • pkozlowski.opensource
      pkozlowski.opensource over 11 years
    • Narretz
      Narretz over 11 years
      kfis' answer uses a directive, so probably exactly what you want.
  • Michael Low
    Michael Low over 11 years
    +1 Interesting idea thanks, I hadn't thought of that.