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

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

我的菜单是这样的:

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

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

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

有提示吗?


当前回答

Here is the solution that I came up with after reading some of the excellent suggestions above. In my particular situation, I was trying to use Bootstrap tabs component as my menu, but didn't want to use the Angular-UI version of this because I want the tabs to act as a menu, where each tab is bookmark-able, rather than the tabs acting as navigation for a single page. (See http://angular-ui.github.io/bootstrap/#/tabs if you're interested in what the Angular-UI version of bootstrap tabs looks like).

I really liked kfis's answer about creating your own directive to handle this, however it seemed cumbersome to have a directive that needed to be placed on every single link. So I've created my own Angular directive which is placed instead once on the ul. Just in case any one else is trying to do the same thing, I thought I'd post it here, though as I said, many of the above solutions work as well. This is a slightly more complex solution as far as the javascript goes, but it creates a reusable component with minimal markup.

下面是指令的javascript和ng:view的路由提供程序:

var app = angular.module('plunker', ['ui.bootstrap']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
        when('/One', {templateUrl: 'one.html'}).
        when('/Two', {templateUrl: 'two.html'}).
        when('/Three', {templateUrl: 'three.html'}).
        otherwise({redirectTo: '/One'});
  }]).
  directive('navTabs', ['$location', function(location) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            var $ul = $(element);
            $ul.addClass("nav nav-tabs");

            var $tabs = $ul.children();
            var tabMap = {};
            $tabs.each(function() {
              var $li = $(this);
              //Substring 1 to remove the # at the beginning (because location.path() below does not return the #)
              tabMap[$li.find('a').attr('href').substring(1)] = $li;
            });

            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                $tabs.removeClass("active");
                tabMap[newPath].addClass("active");
            });
        }

    };

 }]);

然后在你的html中你只需:

<ul nav-tabs>
  <li><a href="#/One">One</a></li>
  <li><a href="#/Two">Two</a></li>
  <li><a href="#/Three">Three</a></li>
</ul>
<ng:view><!-- Content will appear here --></ng:view>

这里是它的活塞:http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview。

其他回答

也有同样的问题。以下是我的解决方案:

.directive('whenActive',
  [
    '$location',
    ($location)->
      scope: true,
      link: (scope, element, attr)->
        scope.$on '$routeChangeSuccess', 
          () ->
            loc = "#"+$location.path()
            href = element.attr('href')
            state = href.indexOf(loc)
            substate = -1

            if href.length > 3
              substate = loc.indexOf(href)
            if loc.length is 2
              state = -1

            #console.log "Is Loc: "+loc+" in Href: "+href+" = "+state+" and Substate = "+substate

            if state isnt -1 or substate isnt -1
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else if href is '#' and loc is '#/'
              element.addClass 'selected'
              element.parent().addClass 'current-menu-item'
            else
              element.removeClass 'selected'
              element.parent().removeClass 'current-menu-item'
  ])

Here is the solution that I came up with after reading some of the excellent suggestions above. In my particular situation, I was trying to use Bootstrap tabs component as my menu, but didn't want to use the Angular-UI version of this because I want the tabs to act as a menu, where each tab is bookmark-able, rather than the tabs acting as navigation for a single page. (See http://angular-ui.github.io/bootstrap/#/tabs if you're interested in what the Angular-UI version of bootstrap tabs looks like).

I really liked kfis's answer about creating your own directive to handle this, however it seemed cumbersome to have a directive that needed to be placed on every single link. So I've created my own Angular directive which is placed instead once on the ul. Just in case any one else is trying to do the same thing, I thought I'd post it here, though as I said, many of the above solutions work as well. This is a slightly more complex solution as far as the javascript goes, but it creates a reusable component with minimal markup.

下面是指令的javascript和ng:view的路由提供程序:

var app = angular.module('plunker', ['ui.bootstrap']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
        when('/One', {templateUrl: 'one.html'}).
        when('/Two', {templateUrl: 'two.html'}).
        when('/Three', {templateUrl: 'three.html'}).
        otherwise({redirectTo: '/One'});
  }]).
  directive('navTabs', ['$location', function(location) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            var $ul = $(element);
            $ul.addClass("nav nav-tabs");

            var $tabs = $ul.children();
            var tabMap = {};
            $tabs.each(function() {
              var $li = $(this);
              //Substring 1 to remove the # at the beginning (because location.path() below does not return the #)
              tabMap[$li.find('a').attr('href').substring(1)] = $li;
            });

            scope.location = location;
            scope.$watch('location.path()', function(newPath) {
                $tabs.removeClass("active");
                tabMap[newPath].addClass("active");
            });
        }

    };

 }]);

然后在你的html中你只需:

<ul nav-tabs>
  <li><a href="#/One">One</a></li>
  <li><a href="#/Two">Two</a></li>
  <li><a href="#/Three">Three</a></li>
</ul>
<ng:view><!-- Content will appear here --></ng:view>

这里是它的活塞:http://plnkr.co/edit/xwGtGqrT7kWoCKnGDHYN?p=preview。

来自@Renan-tomal-fernandes的回答很好,但需要进行一些改进才能正确工作。 事实上,它总是在触发时检测到到主页(/)的链接,即使你在另一个部分。

我稍微改进了一下,这是代码。 我使用Bootstrap,所以活动部分是在<li>元素,而不是<a>。

控制器

$scope.getClass = function(path) {
    var cur_path = $location.path().substr(0, path.length);
    if (cur_path == path) {
        if($location.path().substr(0).length > 1 && path.length == 1 )
            return "";
        else
            return "active";
    } else {
        return "";
    }
}

模板

<div class="nav-collapse collapse">
  <ul class="nav">
    <li ng-class="getClass('/')"><a href="#/">Home</a></li>
    <li ng-class="getClass('/contents/')"><a href="#/contests/">Contents</a></li>
    <li ng-class="getClass('/data/')"><a href="#/data/">Your data</a></li>
  </ul>
</div>

这里有一个简单的方法,可以很好地使用Angular。

<ul>
    <li ng-class="{ active: isActive('/View1') }"><a href="#/View1">View 1</a></li>
    <li ng-class="{ active: isActive('/View2') }"><a href="#/View2">View 2</a></li>
    <li ng-class="{ active: isActive('/View3') }"><a href="#/View3">View 3</a></li>
</ul>

在你的AngularJS控制器中:

$scope.isActive = function (viewLocation) {
     var active = (viewLocation === $location.path());
     return active;
};

这个帖子有许多其他类似的答案。

如何用Angular JS设置引导导航栏活动类?

如果你想把指令的链接放在一个包装器中,而不是选择每个单独的链接(这样更容易查看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,但你可以很容易地改变我所做的过滤等。