如何突出显示当前菜单项?


205

AngularJS在以任何方式active在当前页面的链接上设置类是否有帮助?

我想象有一种神奇的方法可以完成,但是我似乎找不到。

我的菜单如下:

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

并且我在自己的路线中有针对每个控制器的控制器:TasksControllerActionsController

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

有什么提示吗?

Answers:


265

在看

<a ng-class="getClass('/tasks')" href="/tasks">Tasks</a>

在控制器上

$scope.getClass = function (path) {
  return ($location.path().substr(0, path.length) === path) ? 'active' : '';
}

这样,任务链接将在以'/ tasks'开头的任何url中具有活动类(例如'/ tasks / 1 / reports')


4
最终将同时匹配“ /”和“ / anything”,或者如果您有多个具有相似网址的菜单项,例如“ / test”,“ / test / this”,“ / test / this / path”(如果您使用的是/ test,它将突出显示所有这些选项。
Ben Lesh

3
我已将其更改为if($ location.path()== path)和,y path是“ / blah”等
蒂姆

113
我更喜欢这种表示法ngClass="{active: isActive('/tasks')},该方法在isActive()将控制器与标记/样式分离时将返回一个布尔值。
Ed Hinchliffe

6
以防万一有人想知道代码是否不加倍表示路径是否为“ /”,就是这样(对不起格式):$ scope.getClass = function(path){if($ location.path()。 substr(0,path.length)== path){if(path ==“ /” && $ location.path()==“ /”){返回“活动”;} else if(path ==“ /”){返回“”; } return“ active”} else {return“”}}

1
EdHinchliffe已经指出,这混合了标记和逻辑。这也导致路径的重复,并因此可能易于复制和粘贴错误。我发现@kfis的指令方法虽然行数较多,但更可重用,并且可以使标记更整洁。
A. Murray 2013年

86

我建议在链接上使用指令。

但是它还不完美。提防薯条;)

这是指令的javascript:

angular.module('link', []).
  directive('activeLink', ['$location', function (location) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs, controller) {
        var clazz = attrs.activeLink;
        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) {
          if (path === newPath) {
            element.addClass(clazz);
          } else {
            element.removeClass(clazz);
          }
        });
      }
    };
  }]);

这就是它在html中的用法:

<div ng-app="link">
  <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样式:

.active { color: red; }

我不确定“当心哈希爆炸”的意思。看来它将始终有效。您能提供一个反例吗?
Andriy Drozdyuk

7
如果您尝试使用Bootstrap并且需要基于li内a的href的哈希值进行设置,请使用var path = $(element).children("a")[0].hash.substring(1);。这将适用于<li active-link="active"><a href="#/dashboard">Dashboard</a></li>
Dave

2
我会换scope.$watch('location.path()', function(newPath) {scope.$on('$locationChangeStart', function(){
sanfilippopablo 2013年

2
如果您正在使用NG-HREF只是改变: var path = attrs.href;var path = attrs.href||attrs.ngHref;
威廉·尼利

如果您使用Bootstrap并将活动类放在上<li>,则可以更改element.addClass(clazz);element.parent().addClass(clazz);
JamesRLamar 2014年

47

这是一种适用于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设置bootstrap navbar活动类?


1
删除变量,因为它是不必要的。只需返回比较结果即可。return viewLocation === $location.path()
afarazit

33

只是为了在辩论中加上两美分,我制作了一个纯角度模块(没有jQuery),它也可以用于包含数据的哈希URL。(例如#/this/is/path?this=is&some=data

您只需将模块作为依赖项添加auto-active到菜单的祖先之一即可。像这样:

<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/


1
很棒的解决方案,但是它在初始页面加载时不起作用,仅在应用程序运行时才在locationChange上起作用。我更新了您的代码片段以解决该问题。
杰里

@Jarek:谢谢!已实施您的更改。我个人对此没有问题,但是对于应该遇到此问题的人来说,您的解决方案似乎是一个很好的稳定解决方案。
Pylinux

2
如果有人有什么好主意,我现在已经为请求请求创建了一个Github 仓库
Pylinux

我只是修复了一些其他错误,如果您使用ng-href会发生这些错误。可以在这里找到:github.com/Karl-Gustav/autoActive/pull/3
Blake Niemyjski 2014年

如果此脚本允许您指定路径,以便可以激活其他元素,那就太好了。
Blake Niemyjski 2014年

22

就我而言,我通过创建一个负责导航的简单控制器解决了这个问题

angular.module('DemoApp')
  .controller('NavigationCtrl', ['$scope', '$location', function ($scope, $location) {
    $scope.isCurrentPath = function (path) {
      return $location.path() == path;
    };
  }]);

只需将ng-class添加到元素,如下所示:

<ul class="nav" ng-controller="NavigationCtrl">
  <li ng-class="{ active: isCurrentPath('/') }"><a href="#/">Home</a></li>
  <li ng-class="{ active: isCurrentPath('/about') }"><a href="#/about">About</a></li>
  <li ng-class="{ active: isCurrentPath('/contact') }"><a href="#/contact">Contact</a></li>
</ul>

14

对于AngularUI路由器用户:

<a ui-sref-active="active" ui-sref="app">

这将active在所选对象上放置一个类。


2
这是一个ui-router指令,如果您使用内置路由器akangRoute,则该指令不起作用。也就是说,ui-router非常棒。
moljac024 2014年

同意,我最初忘记提及这是仅用于ui路由器的解决方案。
frankie4fingers'2015-10-5

13

有一个ng-class指令,它绑定变量和CSS类。它还接受对象(className与bool值对)。

这是示例,http://plnkr.co/edit/SWZAqj


谢谢,但这不适用于路径:/test1/blahblah,还是可以吗?
Andriy Drozdyuk,2012年

那么,您是说active: activePath=='/test1'路径以给定的字符串开始自动返回“活动”吗?这是某种预定义的运算符或正则表达式吗?
Andriy Drozdyuk,2012年

抱歉,我认为我没有正确理解您的要求。这是我的新猜测,当路由为“ test1 / blahblah”时,您希望同时突出显示“ test1”链接和“ test1 / blahblah”链接。”我是否正确?如果这是必需的,那么您对我的解决方案没有要求工作
Tosh 2012年

3
这是更新的plnkr:plnkr.co/edit/JI5DtK(满足猜测的要求),仅显示替代解决方案。
Tosh 2012年

我看到你在那里做了什么。但是我不喜欢==在html 中反复检查。
Andriy Drozdyuk

13

@ 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>

10

这是我阅读上面的一些出色建议后想到的解决方案。在我的特定情况下,我试图将Bootstrap选项卡组件用作菜单,但不想使用Angular-UI版本,因为我希望这些选项卡充当菜单,其中每个选项卡都可以添加书签,而不是将标签用作单个页面的导航。(如果您对Bootstrap选项卡的Angular-UI版本的外观感兴趣,请参见http://angular-ui.github.io/bootstrap/#/tabs)。

我真的很喜欢kfis关于创建自己的指令来处理此问题的答案,但是要在每个链接上放置一个指令似乎很麻烦。因此,我创建了自己的Angular指令,将其放置在上ul。万一有人试图做同样的事情,我想我应该把它张贴在这里,尽管正如我所说,上述许多解决方案也可以工作。就javascript而言,这是一个稍微复杂的解决方案,但是它创建了具有最小标记的可重用组件。

这是指令的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 。


9

您可以非常简单地实现此功能,下面是一个示例:

<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" : "";
  };
});


4

我在控制器范围之外菜单上遇到了类似的问题。不知道这是最佳解决方案还是推荐的解决方案,但这对我有用。我在我的应用程序配置中添加了以下内容:

var app = angular.module('myApp');

app.run(function($rootScope, $location){
  $rootScope.menuActive = function(url, exactMatch){
    if (exactMatch){
      return $location.path() == url;
    }
    else {
      return $location.path().indexOf(url) == 0;
    }
  }
});

然后在视图中我有:

<li><a href="/" ng-class="{true: 'active'}[menuActive('/', true)]">Home</a></li>
<li><a href="/register" ng-class="{true: 'active'}[menuActive('/register')]">
<li>...</li>

嗯...这似乎比公认的答案更复杂。您能描述一下这一点比那一点的优势吗?
舍甫琴科Drozdyuk

1
在菜单位于ng-view之外的情况下,您将需要它。视图控制器将无法访问外部的任何内容,因此我使用$ rootScope来启用通信。如果您的菜单位于ng-view内部,则使用此解决方案对您没有任何好处。
mrt

4

在Bootstrap 4.1中使用Angular版本6

我能够像下面看到的那样完成它。

在下面的示例中,当URL看到'/ contact'时,则会将主动引导程序添加到html标记中。URL更改后,将其删除。

<ul>
<li class="nav-item" routerLink="/contact" routerLinkActive="active">
    <a class="nav-link" href="/contact">Contact</a>
</li>
</ul>

使用此伪指令,可以在链接的路由变为活动状态时将CSS类添加到元素。

Angular网站上阅读更多内容


3

使用指令(因为我们在这里进行DOM操作),以下内容可能是最接近以“角度方式”进行处理的内容:

$scope.timeFilters = [
  {'value':3600,'label':'1 hour'},
  {'value':10800,'label':'3 hours'},
  {'value':21600,'label':'6 hours'},
  {'value':43200,'label':'12 hours'},
  {'value':86400,'label':'24 hours'},
  {'value':604800,'label':'1 week'}
]

angular.module('whatever', []).directive('filter',function(){
return{
    restrict: 'A',
    template: '<li ng-repeat="time in timeFilters" class="filterItem"><a ng-click="changeTimeFilter(time)">{{time.label}}</a></li>',
    link: function linkFn(scope, lElement, attrs){

        var menuContext = attrs.filter;

        scope.changeTimeFilter = function(newTime){
          scope.selectedtimefilter = newTime;

        }

        lElement.bind('click', function(cevent){
            var currentSelection = angular.element(cevent.srcElement).parent();
            var previousSelection = scope[menuContext];

            if(previousSelection !== currentSelection){
                if(previousSelection){
                    angular.element(previousSelection).removeClass('active')
                }
                scope[menuContext] = currentSelection;

                scope.$apply(function(){
                    currentSelection.addClass('active');
                })
            }
        })
    }
}
})

然后,您的HTML将如下所示:

<ul class="dropdown-menu" filter="times"></ul>

有趣。但menu-item似乎每一行都是多余的。将属性附加到ul元素(例如<ul menu>)可能会更好,但是我不确定是否可能。
Andriy Drozdyuk

刚刚更新为新版本-我现在使用Boostrap下拉菜单作为选择列表,而不是静态的无序列表。
Wesley Hales 2013年

这似乎最像惯用的角度。它似乎符合在stackoverflow.com/questions/14994391/…上给出的建议,并且避免了在视图,href和ng-class中重复路径。
2013年

2

我这样做是这样的:

var myApp = angular.module('myApp', ['ngRoute']);

myApp.directive('trackActive', function($location) {
    function link(scope, element, attrs){
        scope.$watch(function() {
            return $location.path();
        }, function(){
            var links = element.find('a');
            links.removeClass('active');
            angular.forEach(links, function(value){
                var a = angular.element(value);
                if (a.attr('href') == '#' + $location.path() ){
                    a.addClass('active');
                }
            });
        });
    }
    return {link: link};
});

这使您可以在具有track-active指令的部分中具有链接:

<nav track-active>
     <a href="#/">Page 1</a>
     <a href="#/page2">Page 2</a>
     <a href="#/page3">Page 3</a>
</nav>

在我看来,这种方法比其他方法干净得多。

另外,如果您使用的是jQuery,则可以使其更加整洁,因为jQlite仅具有基本的选择器支持。在角度包含之前包含jQuery的干净得多的版本如下所示:

myApp.directive('trackActive', function($location) {
    function link(scope, element, attrs){
        scope.$watch(function() {
            return $location.path();
        }, function(){
            element.find('a').removeClass('active').find('[href="#'+$location.path()+'"]').addClass('active');
        });
    }
    return {link: link};
});

这是一个jsFiddle


2

我对这个问题的解决方案,route.current在有角度的模板中使用。

/tasks菜单中有要突出显示的路线时,可以将自己的属性添加menuItem到模块声明的路线中:

$routeProvider.
  when('/tasks', {
    menuItem: 'TASKS',
    templateUrl: 'my-templates/tasks.html',
    controller: 'TasksController'
  );

然后,您tasks.html可以在模板中使用以下ng-class指令:

<a href="app.html#/tasks" 
    ng-class="{active : route.current.menuItem === 'TASKS'}">Tasks</a>

我认为,这比所有建议的解决方案都干净得多。


1

这是对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>

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


1

这是另一个突出显示活动链接的指令。

主要特点:

  • 与包含动态角度表达式的href配合良好
  • 与哈希爆炸导航兼容
  • 与Bootstrap兼容,其中应将活动类应用于父li,而不是链接本身
  • 如果任何嵌套路径处于活动状态,则允许使链接处于活动状态
  • 如果无效,则允许建立链接

码:

.directive('activeLink', ['$location', 
function($location) {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var path = attrs.activeLink ? 'activeLink' : 'href';
            var target = angular.isDefined(attrs.activeLinkParent) ? elem.parent() : elem;
            var disabled = angular.isDefined(attrs.activeLinkDisabled) ? true : false;
            var nested = angular.isDefined(attrs.activeLinkNested) ? true : false;

            function inPath(needle, haystack) {
                var current = (haystack == needle);
                if (nested) {
                    current |= (haystack.indexOf(needle + '/') == 0);
                }

                return current;
            }

            function toggleClass(linkPath, locationPath) {
                // remove hash prefix and trailing slashes
                linkPath = linkPath ? linkPath.replace(/^#!/, '').replace(/\/+$/, '') : '';
                locationPath = locationPath.replace(/\/+$/, '');

                if (linkPath && inPath(linkPath, locationPath)) {
                    target.addClass('active');
                    if (disabled) {
                        target.removeClass('disabled');
                    }
                } else {
                    target.removeClass('active');
                    if (disabled) {
                        target.addClass('disabled');
                    }
                }
            }

            // watch if attribute value changes / evaluated
            attrs.$observe(path, function(linkPath) {
                toggleClass(linkPath, $location.path());
            });

            // watch if location changes
            scope.$watch(
                function() {
                    return $location.path(); 
                }, 
                function(newPath) {
                    toggleClass(attrs[path], newPath);
                }
            );
        }
    };
}
]);

用法:

带有角表达式的简单示例,假设$ scope.var = 2,则如果location为/ url / 2,则链接将处于活动状态:

<a href="#!/url/{{var}}" active-link>

引导程序示例,父级li将获得活动类:

<li>
    <a href="#!/url" active-link active-link-parent>
</li>

带有嵌套网址的示例,如果任何嵌套网址处于活动状态(即/ url / 1/ url / 2url / 1/2 / ...),则链接将处于活动状态

<a href="#!/url" active-link active-link-nested>

复杂的例子,链接指向一个URL(/ URL1),但将被激活,如果另一个被选择(/ URL2):

<a href="#!/url1" active-link="#!/url2" active-link-nested>

具有禁用链接的示例,如果它不处于活动状态,则将具有“ disabled”类:

<a href="#!/url" active-link active-link-disabled>

所有active-link- *属性都可以任意组合使用,因此可以实现非常复杂的条件。


1

如果您希望在包装器中使用指令的链接,而不是选择每个单独的链接(这使查看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,但是您可以轻松更改我对过滤所做的工作,等等。


1

这是我的两分钱,这很好。

注意:这与子页面不匹配(这是我所需要的)。

视图:

<a ng-class="{active: isCurrentLocation('/my-path')}"  href="/my-path" >
  Some link
</a>

控制器:

// make sure you inject $location as a dependency

$scope.isCurrentLocation = function(path){
    return path === $location.path()
}

1

根据@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="link">
  <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样式:

.active { color: red; }

1

对于使用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>

1

上述指令建议对我都没有帮助。如果您有这样的引导导航栏

<ul class="nav navbar-nav">
    <li><a ng-href="#/">Home</a></li>
    <li><a ng-href="#/about">About</a></li>
  ...
</ul>

(可能是一家$ yo angular初创公司),那么您想添加.active <li>元素类列表,而不是元素本身;即<li class="active">..</li>。所以我这样写:

.directive('setParentActive', ['$location', function($location) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs, controller) {
      var classActive = attrs.setParentActive || 'active',
          path = attrs.ngHref.replace('#', '');
      scope.location = $location;
      scope.$watch('location.path()', function(newPath) {
        if (path == newPath) {
          element.parent().addClass(classActive);
        } else {
          element.parent().removeClass(classActive);
        }
      })
    }
  }
}])

用法set-parent-active; .active是默认设置,因此不需要设置

<li><a ng-href="#/about" set-parent-active>About</a></li>

<li>元素将.active在链接处于活动状态时使用。要使用.active类似的替代类.highlight,只需

<li><a ng-href="#/about" set-parent-active="highlight">About</a></li>

我试过scope。$ on(“ $ routeChangeSuccess”,函数(事件,当前,上一个){applyActiveClass();}); 但它仅在单击链接而不是“页面加载”(单击刷新按钮)时才起作用。看着这个位置对我
有用

0

对我来说,最重要的是根本不要更改引导程序的默认代码。这是我的菜单控制器,它搜索菜单选项,然后添加所需的行为。

file: header.js
function HeaderCtrl ($scope, $http, $location) {
  $scope.menuLinkList = [];
  defineFunctions($scope);
  addOnClickEventsToMenuOptions($scope, $location);
}

function defineFunctions ($scope) {
  $scope.menuOptionOnClickFunction = function () {
    for ( var index in $scope.menuLinkList) {
      var link = $scope.menuLinkList[index];
      if (this.hash === link.hash) {
        link.parentElement.className = 'active';
      } else {
        link.parentElement.className = '';
      }
    }
  };
}

function addOnClickEventsToMenuOptions ($scope, $location) {
  var liList = angular.element.find('li');
  for ( var index in liList) {
    var liElement = liList[index];
    var link = liElement.firstChild;
    link.onclick = $scope.menuOptionOnClickFunction;
    $scope.menuLinkList.push(link);
    var path = link.hash.replace("#", "");
    if ($location.path() === path) {
      link.parentElement.className = 'active';
    }
  }
}

     <script src="resources/js/app/header.js"></script>
 <div class="navbar navbar-fixed-top" ng:controller="HeaderCtrl">
    <div class="navbar-inner">
      <div class="container-fluid">
        <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span> <span class="icon-bar"></span> 
<span     class="icon-bar"></span>
        </button>
        <a class="brand" href="#"> <img src="resources/img/fom-logo.png"
          style="width: 80px; height: auto;">
        </a>
        <div class="nav-collapse collapse">
          <ul class="nav">
            <li><a href="#/platforms">PLATFORMS</a></li>
            <li><a href="#/functionaltests">FUNCTIONAL TESTS</a></li>
          </ul> 
        </div>
      </div>
    </div>
  </div>

0

有同样的问题。这是我的解决方案

.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'
  ])

0

我只是为此写了一条指令。

用法:

<ul class="nav navbar-nav">
  <li active><a href="#/link1">Link 1</a></li>
  <li active><a href="#/link2">Link 2</a></li>
</ul>

实现方式:

angular.module('appName')
  .directive('active', function ($location, $timeout) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        // Whenever the user navigates to a different page...
        scope.$on('$routeChangeSuccess', function () {
          // Defer for other directives to load first; this is important
          // so that in case other directives are used that this directive
          // depends on, such as ng-href, the href is evaluated before
          // it's checked here.
          $timeout(function () {
            // Find link inside li element
            var $link = element.children('a').first();

            // Get current location
            var currentPath = $location.path();

            // Get location the link is pointing to
            var linkPath = $link.attr('href').split('#').pop();

            // If they are the same, it means the user is currently
            // on the same page the link would point to, so it should
            // be marked as such
            if (currentPath === linkPath) {
              $(element).addClass('active');
            } else {
              // If they're not the same, a li element that is currently
              // marked as active needs to be "un-marked"
              element.removeClass('active');
            }
          });
        });
      }
    };
  });

测试:

'use strict';

describe('Directive: active', function () {

  // load the directive's module
  beforeEach(module('appName'));

  var element,
      scope,
      location,
      compile,
      rootScope,
      timeout;

  beforeEach(inject(function ($rootScope, $location, $compile, $timeout) {
    scope = $rootScope.$new();
    location = $location;
    compile = $compile;
    rootScope = $rootScope;
    timeout = $timeout;
  }));

  describe('with an active link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/foo');
    });

    describe('href', function () {
      beforeEach(function () {
        // Create and compile element with directive; note that the link
        // is the same as the current location after the location change.
        element = angular.element('<li active><a href="#/foo">Foo</a></li>');
        element = compile(element)(scope);

        // Broadcast location change; the directive waits for this signal
        rootScope.$broadcast('$routeChangeSuccess');

        // Flush timeout so we don't have to write asynchronous tests.
        // The directive defers any action using a timeout so that other
        // directives it might depend on, such as ng-href, are evaluated
        // beforehand.
        timeout.flush();
      });

      it('adds the class "active" to the li', function () {
        expect(element.hasClass('active')).toBeTruthy();
      });
    });

    describe('ng-href', function () {
      beforeEach(function () {
        // Create and compile element with directive; note that the link
        // is the same as the current location after the location change;
        // however this time with an ng-href instead of an href.
        element = angular.element('<li active><a ng-href="#/foo">Foo</a></li>');
        element = compile(element)(scope);

        // Broadcast location change; the directive waits for this signal
        rootScope.$broadcast('$routeChangeSuccess');

        // Flush timeout so we don't have to write asynchronous tests.
        // The directive defers any action using a timeout so that other
        // directives it might depend on, such as ng-href, are evaluated
        // beforehand.
        timeout.flush();
      });

      it('also works with ng-href', function () {
        expect(element.hasClass('active')).toBeTruthy();
      });
    });
  });

  describe('with an inactive link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/bar');

      // Create and compile element with directive; note that the link
      // is the NOT same as the current location after the location change.
      element = angular.element('<li active><a href="#/foo">Foo</a></li>');
      element = compile(element)(scope);

      // Broadcast location change; the directive waits for this signal
      rootScope.$broadcast('$routeChangeSuccess');

      // Flush timeout so we don't have to write asynchronous tests.
      // The directive defers any action using a timeout so that other
      // directives it might depend on, such as ng-href, are evaluated
      // beforehand.
      timeout.flush();
    });

    it('does not add the class "active" to the li', function () {
      expect(element.hasClass('active')).not.toBeTruthy();
    });
  });

  describe('with a formerly active link', function () {
    beforeEach(function () {
      // Trigger location change
      location.path('/bar');

      // Create and compile element with directive; note that the link
      // is the same as the current location after the location change.
      // Also not that the li element already has the class "active".
      // This is to make sure that a link that is active right now will
      // not be active anymore when the user navigates somewhere else.
      element = angular.element('<li class="active" active><a href="#/foo">Foo</a></li>');
      element = compile(element)(scope);

      // Broadcast location change; the directive waits for this signal
      rootScope.$broadcast('$routeChangeSuccess');

      // Flush timeout so we don't have to write asynchronous tests.
      // The directive defers any action using a timeout so that other
      // directives it might depend on, such as ng-href, are evaluated
      // beforehand.
      timeout.flush();
    });

    it('removes the "active" class from the li', function () {
      expect(element.hasClass('active')).not.toBeTruthy();
    });
  });
});

0

路线:

$routeProvider.when('/Account/', { templateUrl: '/Home/Account', controller: 'HomeController' });

菜单html:

<li id="liInicio" ng-class="{'active':url=='account'}">

控制器:

angular.module('Home').controller('HomeController', function ($scope, $http, $location) {
    $scope.url = $location.url().replace(/\//g, "").toLowerCase();
...

我在这里发现的问题是菜单项仅在加载整个页面时才处于活动状态。加载局部视图后,菜单不会更改。有人知道为什么会发生吗?


0
$scope.getClass = function (path) {
return String(($location.absUrl().split('?')[0]).indexOf(path)) > -1 ? 'active' : ''
}


<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/bookings">MY BOOKING</a></li>
<li class="listing-head" ng-class="getClass('/v/fleets')"><a href="/v/fleets">MY FLEET</a></li>
<li class="listing-head" ng-class="getClass('/v/adddriver')"><a href="/v/adddriver">ADD DRIVER</a></li>
<li class="listing-head" ng-class="getClass('/v/bookings')"><a href="/v/invoice">INVOICE</a></li>
<li class="listing-head" ng-class="getClass('/v/profile')"><a href="/v/profile">MY PROFILE</a></li>
<li class="listing-head"><a href="/v/logout">LOG OUT</a></li>

0

我找到了最简单的解决方案。只是为了比较HTML中的indexOf

var myApp = angular.module('myApp', []);

myApp.run(function($rootScope) {
    $rootScope.$on("$locationChangeStart", function(event, next, current) { 
         $rootScope.isCurrentPath = $location.path();  
    });
});



<li class="{{isCurrentPath.indexOf('help')>-1 ? 'active' : '' }}">
<a href="/#/help/">
          Help
        </a>
</li>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.