如何用Angular JS设置引导导航栏活动类
How to set bootstrap navbar active class with Angular JS?
如果我在bootstrap中有一个导航栏,上面有
项Home | About | Contact
当每个菜单项处于活动状态时,如何设置活动类?也就是说,当角路由在
时,如何设置class="active"
-
#/
- 关于
- 联系人界面
#/about
#/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>
元素中,并且任何时候路由改变,它都会找到匹配的链接,并将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,导航条指令似乎是你正在寻找的:
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');
}
});
});
}
};
});
使用这个指令:
从http://mgcrea.github.io/angular-strap/下载AngularStrap
在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>
这里有一个简单的方法可以很好地与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;
};
如果你使用的是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>
首先,这个问题可以通过多种方式解决。这种方式可能不是最优雅的,但它确实有效。
这是一个简单的解决方案,你应该能够添加到任何项目。当你配置路由时,你可以添加一个"pageKey"或其他属性,你可以用它来关闭。此外,你可以在$route对象的$ routechangessuccess方法上实现一个监听器,以监听路由更改的成功完成。
当处理程序触发时,您获得页键,并使用该键来定位该页需要"ACTIVE"的元素,并应用ACTIVE类。
请记住,你需要一种方法使所有的元素" in 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>
和一个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-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管理部分/嵌套视图感兴趣。
我觉得所有这些答案对我来说都有点太复杂了,抱歉。所以我创建了一个小指令,应该在每个导航栏的基础上工作:
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-class指令和$location来实现它。
<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;
}]);
如果您使用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>
您可以查看文档获取更多信息
你可以在angular表达式中使用条件来实现这一点,例如:
<a href="#" class="{{ condition ? 'active' : '' }}">link</a>
话虽这么说,我确实发现angular指令是更"合适"的方式,尽管外包很多这种迷你逻辑可能会在某种程度上污染你的代码库。
我在开发过程中每隔一段时间就会使用条件来进行GUI样式设计,因为它比创建指令要快一点。我不能告诉你一个实例,它们实际上在代码库中保留了很长时间。最后,我要么把它变成一个指令,要么找到一个更好的方法来解决问题。
如果你不想使用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);
}));
});
}
};
}]);