AngularJS在为当前页面的链接设置一个活动类方面有任何帮助吗?

我想一定有什么神奇的方法可以做到,但我似乎找不到。

我的菜单是这样的:

 <ul>
   <li><a class="active" href="/tasks">Tasks</a>
   <li><a href="/actions">Tasks</a>
 </ul>

我在我的路由中为它们每个都有控制器:TasksController和ActionsController。

但是我想不出一种方法将a链接上的“活动”类绑定到控制器。

有提示吗?


当前回答

我做了一个纯angular模块(没有jQuery),它也可以处理包含数据的散列url。(例如:# /这个/ /路径?这=一些=数据)

您只需将模块作为依赖项添加并自动激活到菜单的一个祖先。是这样的:

<ul auto-active>
    <li><a href="#/">main</a></li>
    <li><a href="#/first">first</a></li>
    <li><a href="#/second">second</a></li>
    <li><a href="#/third">third</a></li>
</ul>

这个模块是这样的:

(function () {
    angular.module('autoActive', [])
        .directive('autoActive', ['$location', function ($location) {
        return {
            restrict: 'A',
            scope: false,
            link: function (scope, element) {
                function setActive() {
                    var path = $location.path();
                    if (path) {
                        angular.forEach(element.find('li'), function (li) {
                            var anchor = li.querySelector('a');
                            if (anchor.href.match('#' + path + '(?=\\?|$)')) {
                                angular.element(li).addClass('active');
                            } else {
                                angular.element(li).removeClass('active');
                            }
                        });
                    }
                }

                setActive();

                scope.$on('$locationChangeSuccess', setActive);
            }
        }
    }]);
}());

(当然,你可以只使用指令部分)

值得注意的是,这并不适用于空哈希值(例如example.com/#或仅example.com),它至少需要example.com/#/或仅example.com#/。但这是自动发生的ngResource之类的。

这是小提琴:http://jsfiddle.net/gy2an/8/

其他回答

对于那些使用ui-router的人,我的答案有点类似于Ender2050,但我更喜欢通过州名测试来做到这一点:

$scope.isActive = function (stateName) {
  var active = (stateName === $state.current.name);
  return active;
};

相应的HTML:

<ul class="nav nav-sidebar">
    <li ng-class="{ active: isActive('app.home') }"><a ui-sref="app.home">Dashboard</a></li>
    <li ng-class="{ active: isActive('app.tiles') }"><a ui-sref="app.tiles">Tiles</a></li>
</ul>

这是一个扩展的kfis指令,我做了允许不同级别的路径匹配。从本质上讲,我发现需要匹配URL路径到一定深度,因为精确匹配不允许嵌套和默认状态重定向。希望这能有所帮助。

    .directive('selectedLink', ['$location', function(location) {
    return {
        restrict: 'A',
        scope:{
            selectedLink : '='
            },
        link: function(scope, element, attrs, controller) {
            var level = scope.selectedLink;
            var path = attrs.href;
            path = path.substring(1); //hack because path does not return including hashbang
            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                var i=0;
                p = path.split('/');
                n = newPath.split('/');
                for( i ; i < p.length; i++) { 
                    if( p[i] == 'undefined' || n[i] == 'undefined' || (p[i] != n[i]) ) break;
                    }

                if ( (i-1) >= level) {
                    element.addClass("selected");
                    } 
                else {
                    element.removeClass("selected");
                    }
                });
            }

        };
    }]);

下面是我如何使用这个链接

<nav>
    <a href="#/info/project/list"  selected-link="2">Project</a>
    <a href="#/info/company/list" selected-link="2">Company</a>
    <a href="#/info/person/list"  selected-link="2">Person</a>
</nav>

该指令将匹配在该指令的属性值中指定的深度级别。只是意味着它可以在其他地方多次使用。

如果你想把指令的链接放在一个包装器中,而不是选择每个单独的链接(这样更容易查看Batarang中的作用域),这也很有效:

  angular.module("app").directive("navigation", [
    "$location", function($location) {
      return {
        restrict: 'A',
        scope: {},
        link: function(scope, element) {
          var classSelected, navLinks;

          scope.location = $location;

          classSelected = 'selected';

          navLinks = element.find('a');

          scope.$watch('location.path()', function(newPath) {
            var el;
            el = navLinks.filter('[href="' + newPath + '"]');

            navLinks.not(el).closest('li').removeClass(classSelected);
            return el.closest('li').addClass(classSelected);
          });
        }
      };
    }
  ]);

加价就是:

    <nav role="navigation" data-navigation>
        <ul>
            <li><a href="/messages">Messages</a></li>
            <li><a href="/help">Help</a></li>
            <li><a href="/details">Details</a></li>
        </ul>
    </nav>

我还应该提到,我在这个例子中使用的是“全脂”jQuery,但你可以很容易地改变我所做的过滤等。

根据@kfis的回答,这是评论,我的建议,最终指令如下:

.directive('activeLink', ['$location', function (location) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs, controller) {
        var clazz = attrs.activeLink;        
        var path = attrs.href||attrs.ngHref;
        path = path.substring(1); //hack because path does not return including hashbang
        scope.location = location;
        scope.$watch('window.location.href', function () {
          var newPath = (window.location.pathname + window.location.search).substr(1);
          if (path === newPath) {
            element.addClass(clazz);
          } else {
            element.removeClass(clazz);
          }
        });
      }
    };
  }]);

下面是它在html中的用法: < div ng-app = "链接" > <a href="#/one" active-link="active"> one </a> <a href="#/two" active-link="active">One</a> <a href="#" active-link="active">home</a> < / div > 之后用css样式: .活跃{颜色:红色;}

你可以很简单地实现它,这里有一个例子:

<div ng-controller="MenuCtrl">
  <ul class="menu">
    <li ng-class="menuClass('home')"><a href="#home">Page1</a></li>
    <li ng-class="menuClass('about')"><a href="#about">Page2</a></li>
  </ul>

</div>

你的控制器应该是这样的:

app.controller("MenuCtrl", function($scope, $location) {
  $scope.menuClass = function(page) {
    var current = $location.path().substring(1);
    return page === current ? "active" : "";
  };
});