如果我在带有项目的引导程序中有一个导航栏
Home | About | Contact
如何为每个菜单项激活时设置活动类?也就是说,当角度路径位于
时,如何设置class="active"
#/
for home #/about
关于关于页面的信息#/contact
用于联系页面答案 0 :(得分:596)
一种非常优雅的方法是使用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();
};
}
答案 1 :(得分:51)
我刚刚编写了一个指令来处理这个问题,所以你可以简单地将属性bs-active-link
添加到父<ul>
元素,每当路由改变时,它会找到匹配的链接,并添加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');
};
});
});
}
}
}]);
答案 2 :(得分:38)
你可以查看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');
}
});
});
}
};
});
使用此指令:
在bootstrap.js之后在页面上包含脚本:
<script src="lib/angular-strap.js"></script>
将指令添加到您的模块中:
angular.module('myApp', ['$strap.directives'])
将指令添加到导航栏:
<div class="navbar" bs-navbar>
在每个导航项上添加正则表达式:
<li data-match-route="/about"><a href="#/about">About</a></li>
答案 3 :(得分:33)
这是一个适用于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;
};
答案 4 :(得分:11)
如果您正在使用Angular路由器,RouterLinkActive directive可以非常优雅地使用:
<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>
答案 5 :(得分:8)
首先,这个问题可以通过很多方式解决。这种方式可能不是最优雅的,但它确实有效。
这是一个简单的解决方案,您应该能够添加到任何项目中。您可以在配置可用于关闭的路由时添加“pageKey”或其他属性。此外,您可以在$ route对象的$ routeChangeSuccess方法上实现一个侦听器,以侦听路由更改的成功完成。
当您的处理程序触发时,您获取页面键,并使用该键来查找此页面需要“ACTIVE”的元素,并应用ACTIVE类。
请记住,您需要一种方法使所有元素“处于活动状态”。正如你所看到我在我的导航项目上使用.pageKey类将它们全部关闭,我正在使用.pageKey_ {PAGEKEY}来单独打开它们。将它们全部切换为非活动状态将被视为一种天真的方法,可能通过使用先前的路由仅使活动项处于非活动状态来获得更好的性能,或者您可以将jquery选择器更改为仅选择要使其处于非活动状态的活动项。使用jquery选择所有活动项可能是最好的解决方案,因为它可以确保在前一个路径上可能存在任何css错误的情况下清除当前路由的所有内容。
这意味着改变这行代码:
$(".pagekey").toggleClass("active", false);
到这个
$(".active").toggleClass("active", false);
以下是一些示例代码:
给出
的引导导航栏<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>
和角度模块和控制器如下:
<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>
答案 6 :(得分:7)
您实际上可以使用angular-ui-utils'ui-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感兴趣管理部分/嵌套视图。
答案 7 :(得分:6)
我发现所有这些答案对我来说有点复杂,抱歉。所以我创建了一个小指令,它应该基于每个导航栏工作:
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>
答案 8 :(得分:5)
我使用带有$ location的ng-class指令来实现它。
<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;
}]);
答案 9 :(得分:4)
您可以使用角度表达式中的条件来实现此目的,例如:
<a href="#" class="{{ condition ? 'active' : '' }}">link</a>
话虽这么说,我确实发现一个角度指令是更“正确”的做法,即使外包很多这种迷你逻辑可能会对你的代码库产生一些污染。
我在开发过程中偶尔使用条件进行GUI样式化,因为它比创建指令要快一些。我无法告诉你一个实例,虽然它们实际上长期存在于代码库中。最后,我要么把它变成一个指令,要么找到一个更好的方法来解决问题。
答案 10 :(得分:4)
如果您使用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>
您可以查看docs以获取更多信息。
答案 11 :(得分:3)
如果你不想使用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
答案 12 :(得分:3)
继承我的看法。这篇文章中的一些答案组合。我的情况略有不同,所以我的解决方案是将菜单分成自己的模板,在指令定义Ojbect中使用,然后将我的导航栏添加到我需要的页面。基本上,我有一个登录页面,我不想包含我的菜单,所以我使用ngInclude并在登录时插入此指令:
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;
}
}
}
});
<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>
<comp-navbar/>
希望这有帮助
答案 13 :(得分:2)
扩展myl答案,我需要这个来处理这样的结构。
-index
-events&LT; -active
---事件列表
---事件编辑
--- event-map&lt; -clicked
-places
---地方列表
---地方编辑
---地方映射
所以我不得不使用indexOf代替匹配,以便验证格式化为匹配条件的子链接。所以对于'事件':
<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;
};}
答案 14 :(得分:2)
这是一个简单的解决方案
<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>
答案 15 :(得分:1)
使用对象作为开关变量。
您可以使用以下方法非常简单地内联:
<ul class="nav navbar-nav">
<li ng-class="{'active':switch.linkOne}" ng-click="switch = {linkOne: true}"><a href="/">Link One</a></li>
<li ng-class="{'active':switch.linkTwo}" ng-click="switch = {link-two: true}"><a href="/link-two">Link Two</a></li>
</ul>
每次单击链接时,切换对象都会被新对象替换,其中只有正确的切换对象属性为true。未定义的属性将被评估为false,因此依赖于它们的元素将不会分配活动的类。
答案 16 :(得分:1)
感谢@Pylinux。我已经使用了他的技术,并修改了它以支持&#34;一个&#34;下拉菜单的级别(sub ul / li),因为这是我需要的。在下面的小提琴链接中查看它。
根据pylinux的答案 - http://jsfiddle.net/abhatia/en4qxw6g/
更新了小提琴我进行了以下三项更改,以支持一个级别的下拉菜单:
1。为&#34; a&#34;添加了dd(下拉列表)的类值。 li下的元素需要有子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;}
希望这对希望实现单级下拉菜单的人有所帮助。
答案 17 :(得分:1)
<强>的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>
答案 18 :(得分:1)
结合@ Olivier的AngularStrap答案,我还实现了kevinknelson的答案:https://github.com/twbs/bootstrap/issues/9013。
本地,Bootstrap3导航栏不是为单页(例如Angular)应用程序设计的,因此在小屏幕上的菜单在点击时不会折叠。
答案 19 :(得分:0)
只是为了在辩论中添加我的两分钱,我已经制作了一个纯角度模块(没有jquery),它也可以使用包含数据的哈希网址。 (i.g. #/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);
}
}
}]);
}());
*(您当然可以使用指令部分)
**同样值得注意的是,这不适用于空哈希(i.g. example.com/#
或仅example.com
)它至少需要example.com/#/
或只是example.com#/
。但这会在ngResource等情况下自动发生。
答案 20 :(得分:0)
我建议在链接上使用指令。 Here是小提琴。
但它还不完美。注意hashbangs;)
以下是javascript for directive:
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; }
答案 21 :(得分:0)
这回答很久但我想我会分享我的方式:
.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"
答案 22 :(得分:0)
这是另一个可能感兴趣的人的解决方案。这样做的好处是它具有较少的依赖性。哎呀,没有网络服务器也可以。所以它完全是客户端的。
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模型动态生成链接。魔术发生在控制器中为此导航栏定义的方法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 : "";
};
});
说明:
使用selectTab()
指令调用 ng-click
方法。因此,单击链接时,变量selectedTab
将设置为此链接的名称。在HTML中,您可以看到调用此方法时没有任何“主页”选项卡参数,以便在页面加载时突出显示该方法。
getTabClass()
方法通过HTML中的ng-class
指令调用。此方法检查它所在的选项卡是否与selectedTab
变量的值相同。如果为true,则返回“active”,否则返回“”,它由ng-class
指令作为类名应用。然后,您应用于课程active
的任何CSS都将应用于所选标签。
答案 23 :(得分:0)
只是您必须添加所需的active
- 类,其中包含所需的颜色代码。
例如:ng-class="{'active': currentNavSelected}" ng-click="setNav"
答案 24 :(得分:0)
这对我有用:
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)来添加类active
$('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>
如果你在www.somesite.com/ee thaen ee是&#39; app&#39;这将使用页面网址自然地添加课程活动并将你的背景颜色设为红色。它将是活跃的
答案 25 :(得分:0)
您也可以使用此有效链接指令https://stackoverflow.com/a/23138152/1387163
当地理位置匹配 / url :
时,父li会获得有效课程<li>
<a href="#!/url" active-link active-link-parent>
</li>