如何设置与Angular JS引导的navbar活动类?

如果我有一个导航栏的项目引导

Home | About | Contact 

当每个菜单项处于活动状态时,如何设置活动类? 也就是说,当angular度路线是在什么时候,我怎么能设置class="active"

  1. #/为家
  2. #/about为关于页面
  3. #/contact的联系人页面

一个非常好的方法是使用ng-controller在ng-view之外运行一个控制器:

 <div class="collapse navbar-collapse" ng-controller="HeaderController"> <ul class="nav navbar-nav"> <li ng-class="{ active: isActive('/')}"><a href="/">Home</a></li> <li ng-class="{ active: isActive('/dogs')}"><a href="/dogs">Dogs</a></li> <li ng-class="{ active: isActive('/cats')}"><a href="/cats">Cats</a></li> </ul> </div> <div ng-view></div> 

并包含在controllers.js中:

 function HeaderController($scope, $location) { $scope.isActive = function (viewLocation) { return viewLocation === $location.path(); }; } 

我只是写了一个指令来处理这个问题,所以你可以简单地将属性bs-active-link到父元素<ul> ,并且每当路由改变的时候,它都会find匹配的链接,并将active类添加到对应的<li>

你可以在这里看到它的行动: http : //jsfiddle.net/8mcedv3b/

HTML示例:

 <ul class="nav navbar-nav" bs-active-link> <li><a href="/home">Home</a></li> <li><a href="/contact">Contact</a></li> </ul> 

使用Javascript:

 angular.module('appName') .directive('bsActiveLink', ['$location', function ($location) { return { restrict: 'A', //use as attribute replace: false, link: function (scope, elem) { //after the route has changed scope.$on("$routeChangeSuccess", function () { var hrefs = ['/#' + $location.path(), '#' + $location.path(), //html5: false $location.path()]; //html5: true angular.forEach(elem.find('a'), function (a) { a = angular.element(a); if (-1 !== hrefs.indexOf(a.attr('href'))) { a.parent().addClass('active'); } else { a.parent().removeClass('active'); }; }); }); } } }]); 

你可以看看AngularStrap ,navbar指令似乎是你正在寻找的:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js

 .directive('bsNavbar', function($location) { 'use strict'; return { restrict: 'A', link: function postLink(scope, element, attrs, controller) { // Watch for the $location scope.$watch(function() { return $location.path(); }, function(newValue, oldValue) { $('li[data-match-route]', element).each(function(k, li) { var $li = angular.element(li), // data('match-rout') does not work with dynamic attributes pattern = $li.attr('data-match-route'), regexp = new RegExp('^' + pattern + '$', ['i']); if(regexp.test(newValue)) { $li.addClass('active'); } else { $li.removeClass('active'); } }); }); } }; }); 

要使用这个指令:

  1. http://mgcrea.github.io/angular-strap/下载AngularStrap

  2. 在bootstrap.js之后在脚本中join脚本:
    <script src="lib/angular-strap.js"></script>

  3. 将指令添加到您的模块中:
    angular.module('myApp', ['$strap.directives'])

  4. 将该指令添加到您的导航栏中:
    <div class="navbar" bs-navbar>

  5. 在每个导航项中添加正则expression式:
    <li data-match-route="/about"><a href="#/about">About</a></li>

这是一个简单的方法,适用于Angular。

 <ul class="nav navbar-nav"> <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; }; 

首先,这个问题可以通过很多方法解决。 这种方式可能不是最优雅的,但它的作品。

这是一个简单的解决scheme,你应该可以添加到任何项目。 您可以在configuration路线时添加“pageKey”或其他属性,以便用于closures。 此外,您可以在$ route对象的$ routeChangeSuccess方法上实现一个侦听器,以侦听成功完成路由更改。

当你的处理器触发你得到页键,并使用该键来定位这个页面需要为“ACTIVE”的元素,并且应用ACTIVE类。

请记住,您需要一种方法来使所有元素“IN ACTIVE”。 正如你可以看到我使用我的导航项目上的.pageKey类来closures它们,我使用.pageKey_ {PAGEKEY}来单独打开它们。 将它们全部切换到非活动状态将被认为是一种天真的方法,可能通过使用前面的路线使活动项目处于非活动状态,从而获得更好的性能,或者可以更改jqueryselect器以仅select要激活的活动项目。 使用jqueryselect所有活动的项目可能是最好的解决scheme,因为它可以确保当前路线的一切都被清除,以防在前面的路线中可能存在的任何css错误。

这将意味着改变这一行代码:

 $(".pagekey").toggleClass("active", false); 

到这一个

 $(".active").toggleClass("active", false); 

这是一些示例代码:

给定一个bootstrap导航栏

 <div class="navbar navbar-inverse"> <div class="navbar-inner"> <a class="brand" href="#">Title</a> <ul class="nav"> <li><a href="#!/" class="pagekey pagekey_HOME">Home</a></li> <li><a href="#!/page1/create" class="pagekey pagekey_CREATE">Page 1 Create</a></li> <li><a href="#!/page1/edit/1" class="pagekey pagekey_EDIT">Page 1 Edit</a></li> <li><a href="#!/page1/published/1" class="pagekey pagekey_PUBLISH">Page 1 Published</a></li> </ul> </div> </div> 

而angular度模块和控制器如下所示:

 <script type="text/javascript"> function Ctrl($scope, $http, $routeParams, $location, $route) { } angular.module('BookingFormBuilder', []). config(function ($routeProvider, $locationProvider) { $routeProvider. when('/', { template: 'I\'m on the home page', controller: Ctrl, pageKey: 'HOME' }). when('/page1/create', { template: 'I\'m on page 1 create', controller: Ctrl, pageKey: 'CREATE' }). when('/page1/edit/:id', { template: 'I\'m on page 1 edit {id}', controller: Ctrl, pageKey: 'EDIT' }). when('/page1/published/:id', { template: 'I\'m on page 1 publish {id}', controller: Ctrl, pageKey: 'PUBLISH' }). otherwise({ redirectTo: '/' }); $locationProvider.hashPrefix("!"); }).run(function ($rootScope, $http, $route) { $rootScope.$on("$routeChangeSuccess", function (angularEvent, currentRoute, previousRoute) { var pageKey = currentRoute.pageKey; $(".pagekey").toggleClass("active", false); $(".pagekey_" + pageKey).toggleClass("active", true); }); }); </script> 

你实际上可以使用angular-ui-utilsui-route指令:

 <a ui-route ng-href="/">Home</a> <a ui-route ng-href="/about">About</a> <a ui-route ng-href="/contact">Contact</a> 

要么:

头控制器

 /** * Header controller */ angular.module('myApp') .controller('HeaderCtrl', function ($scope) { $scope.menuItems = [ { name: 'Home', url: '/', title: 'Go to homepage.' }, { name: 'About', url: '/about', title: 'Learn about the project.' }, { name: 'Contact', url: '/contact', title: 'Contact us.' } ]; }); 

索引页面

 <!-- index.html: --> <div class="header" ng-controller="HeaderCtrl"> <ul class="nav navbar-nav navbar-right"> <li ui-route="{{menuItem.url}}" ng-class="{active: $uiRoute}" ng-repeat="menuItem in menuItems"> <a ng-href="#{{menuItem.url}}" title="{{menuItem.title}}"> {{menuItem.name}} </a> </li> </ul> </div> 

如果您使用的是ui-utils,您可能也会对ui-router感兴趣,来pipe理部分/嵌套的视图。

我发现所有这些答案对我来说都有些复杂,对不起。 所以我创build了一个应该在每个导航栏上工作的小指令:

 app.directive('activeLink', function () { return { link: function (scope, element, attrs) { element.find('.nav a').on('click', function () { angular.element(this) .parent().siblings('.active') .removeClass('active'); angular.element(this) .parent() .addClass('active'); }); } }; }); 

用法:

 <ul class="nav navbar-nav navbar-right" active-link> <li class="nav active"><a href="home">Home</a></li> <li class="nav"><a href="foo">Foo</a></li> <li class="nav"><a href="bar">Bar</a></li> </ul> 

我用ng位置的指令来实现它。

 <ul class="nav"> <li data-ng-class="{active: ($location.path() == '/') }"> <a href="#/">Carpeta Amarilla</a> </li> <li class="dropdown" data-ng-class="{active: ($location.path() == '/auditoria' || $location.path() == '/auditoria/todos') }"> <a class="dropdown-toggle" data-toggle="dropdown" href="#"> Auditoria <b class="caret"></b> </a> <ul class="dropdown-menu pull-right"> <li data-ng-class="{active: ($location.path() == '/auditoria') }"> <a href="#/auditoria">Por Legajo</a> </li> <li data-ng-class="{active: ($location.path() == '/auditoria/todos') }"> <a href="#/auditoria/todos">General</a> </li> </ul> </li> </ul> 

它需要导航栏位于主控制器内,可以像这样访问$ location服务:

 bajasApp.controller('MenuCntl', ['$scope','$route', '$routeParams', '$location', function MenuCntl($scope, $route, $routeParams, $location) { $scope.$route = $route; $scope.$location = $location; $scope.$routeParams = $routeParams; }]); 

你可以在一个angular度expression式中使用条件来实现这一点,例如:

 <a href="#" class="{{ condition ? 'active' : '' }}">link</a> 

这就是说,我确实发现一个angular度指令是做得更“正确”的方法,尽pipe外包大量的这个微型逻辑可能会污染你的代码库。

我在开发过程中每隔一段时间使用一次GUI样式的条件,因为它比创build指令快一点。 虽然他们实际上一直在代码库里呆了很长时间,但是我不能告诉你。 最后,我要么把它变成一个指令,要么找一个更好的方法来解决这个问题。

如果你使用ui-router ,下面的例子应该基于@ DanPantry对接受的答案的评论来满足你的需求,而不需要添加任何控制器端代码:

 <div class="collapse navbar-collapse" ng-controller="HeaderController"> <ul class="nav navbar-nav"> <li ui-sref-active="active"><a ui-sref="app.home()" href="/">Home</a></li> <li ui-sref-active="active"><a ui-sref="app.dogs()" href="/dogs">Dogs</a></li> <li ui-sref-active="active"><a ui-sref="app.cats()" href="/cats">Cats</a></li> </ul> </div> <div ng-view></div> 

您可以查看文档以了解更多信息。

如果你不想使用AngularStrap,那么这个指令应该做的伎俩! 这是对https://stackoverflow.com/a/16231859/910764的修改。;

JavaScript的

 angular.module('myApp').directive('bsNavbar', ['$location', function ($location) { return { restrict: 'A', link: function postLink(scope, element) { scope.$watch(function () { return $location.path(); }, function (path) { angular.forEach(element.children(), (function (li) { var $li = angular.element(li), regex = new RegExp('^' + $li.attr('data-match-route') + '$', 'i'), isActive = regex.test(path); $li.toggleClass('active', isActive); })); }); } }; }]); 

HTML

 <ul class="nav navbar-nav" bs-navbar> <li data-match-route="/home"><a href="#/home">Home</a></li> <li data-match-route="/about"><a href="#/about">About</a></li> </ul> 

注意:上面的HTML类假定您正在使用Bootstrap 3.x

inheritance人我的承担。 在这篇文章中find答案的一小部分。 我有一个稍微不同的情况,所以我的解决scheme涉及将菜单分离成自己的模板,以便在指令定义Ojbect中使用,然后将我的导航栏添加到我需要的页面。 基本上,我有一个login页面,我不想包括我的菜单,所以我使用ngInclude并login时插入此指令:

指示:

 module.directive('compModal', function(){ return { restrict: 'E', replace: true, transclude: true, scope: true, templateUrl: 'templates/menu.html', controller: function($scope, $element, $location){ $scope.isActive = function(viewLocation){ var active = false; if(viewLocation === $location.path()){ active = true; } return active; } } } }); 

DIRECTIVE TEMPLATE(templates / menu.html)

 <ul class="nav navbar-nav"> <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> 

HTML包括指示

 <comp-navbar/> 

希望这可以帮助

扩展myl的答案,我需要这个来处理这样的结构。

-指数

-events <-active
– -活动列表
—事件编辑
— event-map <-clicked

-places
—地方列表
—地方编辑
—地方地图

所以,而不是匹配,我不得不使用indexOf,以validation格式匹配条件的儿童链接。 所以对于“事件”:

 <li ng-class="{ active: isActive('/event')}" class="divider-vertical dropdown"> function NavController($scope, $location) { $scope.isActive = function (viewLocation) { var s=false; if($location.path().indexOf(viewLocation) != -1){ s = true; } return s; };} 

这是一个简单的解决scheme

 <ul class="nav navbar-nav navbar-right navbar-default menu"> <li ng-class="menuIndice == 1 ? 'active':''"> <a ng-click="menuIndice = 1" href="#/item1">item1</a> </li> <li ng-class="menuIndice == 2 ? 'active':''"> <a ng-click="menuIndice = 2" href="#/item2">item2</a> </li> <li ng-class="menuIndice == 3 ? 'active':''"> <a ng-click="menuIndice = 3" href="#/item3">item3</a> </li> </ul> 

结合@ Olivier的AngularStrap答案,我也实现了kevinknelson的答案: https : //github.com/twbs/bootstrap/issues/9013 。

本质上,Bootstrap3导航栏不是为单页面(例如Angular)应用程序而devise的,因此当小屏幕上的菜单在点击时不会崩溃。

JavaScript的

 /** * Main AngularJS Web Application */ var app = angular.module('yourWebApp', [ 'ngRoute' ]); /** * Setup Main Menu */ app.controller('MainNavCtrl', [ '$scope', '$location', function ( $scope, $location) { $scope.menuItems = [ { name: 'Home', url: '/home', title: 'Welcome to our Website' }, { name: 'ABOUT', url: '/about', title: 'Know about our work culture' }, { name: 'CONTACT', url: '/contact', title: 'Get in touch with us' } ]; $scope.isActive = function (viewLocation) { return viewLocation === $location.path(); }; }]); 

HTML

  <div class="navbar-collapse collapse" ng-controller="MainNavCtrl"> <ul id="add-magic-line" class="nav navbar-nav navbar-right"> <li data-ng-class="{current_page_item: isActive('{{ menuItem.url }}')}" data-ng-repeat="menuItem in menuItems"> <a data-ng-href="#{{menuItem.url}}" title="{{menuItem.title}}"> {{menuItem.name}} </a> </li> </ul> </div> 

感谢@Pylinux 。 我已经使用他的技术,并修改它支持“一”级下拉菜单(sub ul /李),因为这是我所需要的。 在下面的小提琴链接中看到它的行动。

基于pylinux的答案更新小提琴 – http://jsfiddle.net/abhatia/en4qxw6g/

为了支持一级下拉菜单,我做了以下三个更改:
1.为li下的“a”元素添加了dd(dropdown)类的值,该元素需要具有子ul列表。

  <li><a class="dd">This link points to #/fun5</a> <ul> <li><a href="#/fun6?some=data">This link points to #/fun6</a> </li> <li><a href="#/fun7?some=data">This link points to #/fun7</a> </li> <li><a href="#/fun8?some=data">This link points to #/fun8</a> </li> <li><a href="#/fun9?some=data">This link points to #/fun9</a> </li> </ul> </li> 

2.更新的Javascript添加以下新的逻辑。

  if(angular.element(li).parent().parent().children('a').hasClass("dd")) {angular.element(li).parent().parent().children('a.dd').addClass('active');} 

3.更新CSS添加以下内容:

 a.active {background-color:red;} 

希望这将有助于有人希望实现单级下拉菜单。

如果您正在使用Angular路由器,则可以非常优雅地使用RouterLinkActive指令 :

 <ul class="navbar-nav"> <li class="nav-item"><a class="nav-link" routerLink="home" routerLinkActive="active">Home</a></li> <li class="nav-item"><a class="nav-link" routerLink="gallery" routerLinkActive="active">Gallery</a></li> <li class="nav-item"><a class="nav-link" routerLink="pricing" routerLinkActive="active">Prices</a></li> <li class="nav-item"><a class="nav-link" routerLink="contact" routerLinkActive="active">Contact</a></li> </ul> 

您也可以使用此主动链接指令https://stackoverflow.com/a/23138152/1387163

当位置匹配/url时,李老师将获得活跃的课程:

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

我build议在链接上使用指令。 这是小提琴。

但它还不完美。 注意hashbangs;)

这里是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; } 

只是为了在辩论中添加我的两分钱,我做了一个纯粹的angular度模块(没有jQuery),它也可以处理包含数据的哈希URL。 ( ig #/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); } } }]); }()); 

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

**还值得注意的是,这对于空的哈希( ig example.com/#或者example.com )不起作用,它至less需要example.com/#/或者example.com#/ 。 但是这会自动发生ngResource之类的。

  • 这里是小提琴: http : //jsfiddle.net/gy2an/8/
  • 这里是github: https : //github.com/Karl-Gustav/autoActive
  • 这是我的原始答案: https : //stackoverflow.com/a/22282124/1465640

这为我做了诡计:

  var domain = '{{ DOMAIN }}'; // www.example.com or dev.example.com var domain_index = window.location.href.indexOf(domain); var long_app_name = window.location.href.slice(domain_index+domain.length+1); // this turns http://www.example.com/whatever/whatever to whatever/whatever app_name = long_app_name.slice(0, long_app_name.indexOf('/')); //now you are left off with just the first whatever which is usually your app name 

那么你使用jquery(与angular度也是)添加类活动

 $('nav a[href*="' + app_name+'"]').closest('li').addClass('active'); 

当然还有CSS:

 .active{background:red;} 

这工作,如果你有你的HTML这样的:

 <ul><li><a href="/ee">ee</a></li><li><a href="/dd">dd</a></li></ul> 

这将无意中添加类活动使用页面的url和颜色的背景红色,如果你在www.somesite.com/ee thaen ee是“应用程序”,它将是积极的

这是很长的回答,但我想我会分享我的方式:

 .run(function($rootScope, $state){ $rootScope.$state = $state; }); 

模板:

 <ul class="nav navbar-nav"> <li ng-class="{ active: $state.contains('View1') }"><a href="...">View 1</a></li> <li ng-class="{ active: $state.contains('View2') }"><a href="...">View 2</a></li> <li ng-class="{ active: $state.contains('View3') }"><a href="...">View 3</a></li> </ul> 

对于那些使用ui-router

 <ul class="nav navbar-nav"> <li ui-sref-active="active"><a href="...">View 1</a></li> <li ui-sref-active="active"><a href="...">View 2</a></li> <li ui-sref-active="active"><a href="...">View 3</a></li> </ul> 

对于完全匹配(例如嵌套状态?),使用$state.name === 'full/path/to/state'ui-sref-active-eq="active"

对于任何可能感兴趣的人来说,这是另一个解 这样做的好处是它具有较less的依赖关系。 哎呀,它没有一个networking服务器也工作。 所以这完全是客户端。

HTML:

 <nav class="navbar navbar-inverse" ng-controller="topNavBarCtrl""> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-home" aria-hidden="true"></span></a> </div> <ul class="nav navbar-nav"> <li ng-click="selectTab()" ng-class="getTabClass()"><a href="#">Home</a></li> <li ng-repeat="tab in tabs" ng-click="selectTab(tab)" ng-class="getTabClass(tab)"><a href="#">{{ tab }}</a></li> </ul> </div> 

说明:

在这里,我们使用ng-repeat指令从angularjs模型dynamic地生成链接。 魔术发生在下面介绍的navbar的控制器中定义的方法selectTab()getTabClass()方法中。

控制器:

 angular.module("app.NavigationControllersModule", []) // Constant named 'activeTab' holding the value 'active'. We will use this to set the class name of the <li> element that is selected. .constant("activeTab", "active") .controller("topNavBarCtrl", function($scope, activeTab){ // Model used for the ng-repeat directive in the template. $scope.tabs = ["Page 1", "Page 2", "Page 3"]; var selectedTab = null; // Sets the selectedTab. $scope.selectTab = function(newTab){ selectedTab = newTab; }; // Sets class of the selectedTab to 'active'. $scope.getTabClass = function(tab){ return selectedTab == tab ? activeTab : ""; }; }); 

说明:

使用ng-click指令调用selectTab()方法。 所以点击链接时,variablesselectedTab被设置为这个链接的名字。 在HTML中,你可以看到这个方法被调用时没有Home标签的任何参数,所以当页面加载的时候它会被高亮显示。

getTabClass()方法是通过HTML中的ng-class指令调用的。 此方法检查它所在的选项卡是否与selectedTabvariables的值相同。 如果为true,则返回“active”,否则返回由ng-class指令作为类名应用的“”。 然后,无论你已经申请到类active CSS将被应用到选定的选项卡。

只要你必须添加所需的active类与所需的颜色代码。

例如: ng-class="{'active': currentNavSelected}" ng-click="setNav"