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

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

Home | About | Contact

当每个菜单项处于活动状态时,如何为它们设置活动类?也就是说,当角路由位于时,如何设置class="active"

  1. #/为家
  2. #/about用于关于页面
  3. #/contact用于联系页面
241298 次浏览

首先,这个问题可以用很多方法来解决。这种方式可能不是最优雅的,但它确实有效。

这里有一个简单的解决方案,你应该能够添加到任何项目。当你配置你的路由时,你可以添加一个“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>

你可以看看AngularStrap,导航栏指令似乎就是你要找的:

https://github.com/mgcrea/angular-strap/blob/master/src/navbar/navbar.js < a href = " 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. 下载AngularStrap from http://mgcrea.github.io/angular-strap/

  2. 在bootstrap.js:
    后在你的页面上包含脚本 李<script src="lib/angular-strap.js"></script> < / p > < / >

  3. 在你的模块中添加指令:
    angular.module('myApp', ['$strap.directives']) < / p > < / >

  4. 将指令添加到导航栏:
    <div class="navbar" bs-navbar> < / p > < / >

  5. 在每个nav项上添加正则表达式:
    <li data-match-route="/about"><a href="#/about">About</a></li> < / p > < / >

你可以在角表达式中使用条件来实现这一点,例如:

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

话虽如此,我确实发现angular指令是更“合适”的方式,即使外包大量这种微型逻辑会在一定程度上污染你的代码库。

在开发过程中,我每隔一段时间就会使用条件来进行GUI样式化,因为这比创建指令要快一些。但我无法告诉你一个实例,它们实际上在代码库中保留了很长时间。最后,我要么把它变成一个指令,要么找到一个更好的方法来解决问题。

我使用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;
}]);

这里有一个简单的方法,可以很好地使用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;
};

一个非常优雅的方法是使用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();
};
}

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

指数

< p > -events<积极< br > ——事件列表< br > ——event-edit < br > ——事件映射& lt;点击< / p > < p >——< br > ——place-list < br > ——place-edit < br > ——place-map < / p >

所以不是匹配,我必须使用indexOf,以验证子链接的格式匹配条件。对于'events':

<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;
};}

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

Bootstrap3导航栏本来就不是为单页面(比如Angular)应用设计的,因此当菜单在小屏幕上时,点击时不会崩溃。

我刚刚写了一个指令来处理这个问题,所以你可以简单地将属性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://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);
}));
});
}
};
}]);

超文本标记语言

<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类假设你正在使用引导3.倍

你也可以使用这个active-link指令https://stackoverflow.com/a/23138152/1387163

父类li将在location匹配/ url时获得活动类:

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

以下是我的看法。在这篇文章中找到了一些答案的组合。我有一个稍微不同的情况下,所以我的解决方案涉及到分离菜单到自己的模板,在指令定义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;


}
}
}
});

指令模板(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/>

希望这能有所帮助

这对我来说很管用:

  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>

这将自动添加类活跃使用页面url和颜色你的背景为红色,如果你在www.somesite.com/ee thaen ee是'应用程序',它将是活跃的

我建议在链接上使用一个指令。 在这里是小提琴。

但它还不完美。小心哈希邦;)

下面是指令的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-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 < / >强感兴趣,用于管理部分/嵌套视图。

只是为了补充我的观点,我做了一个纯angular模块(没有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之类的。

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();
};
}]);

超文本标记语言

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

我觉得这些答案对我来说有点太复杂了,抱歉。所以我创建了一个小指令,应该在每个导航条的基础上工作:

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>

这是一个简单的解决方案

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

感谢@Pylinux。我使用了他的技术,并对其进行了修改,以支持“一级”下拉菜单(sub ul/li),因为这是我所需要的。在下面的小提琴链接中看到它的实际操作。

根据pylinux的答案http://jsfiddle.net/abhatia/en4qxw6g/更新了Fiddle

为了支持一级下拉菜单,我做了以下三个修改:
1。为li下的“a”元素添加了一个类值dd(下拉),该元素需要有子ul列表。< / p >
         <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;}

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

这是一个很长的回答,但我想分享我的方法:

.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"

这里有另一个解决方案,谁可能感兴趣。这样做的好处是它的依赖关系更少。见鬼,它也可以在没有网络服务器的情况下工作。所以这完全是客户端的。

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中,您可以看到这个方法在没有任何Home选项卡参数的情况下被调用,以便在页面加载时突出显示它。

getTabClass()方法是通过HTML中的ng-class指令调用的。这个方法检查它所在的选项卡是否与selectedTab变量的值相同。如果为真,则返回"active",否则返回"",它被ng-class指令应用为类名。然后,无论你应用到类active的css将被应用到所选的选项卡。

你只需要添加所需的active-class和所需的颜色代码。

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

如果你使用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路由器,则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>

使用一个对象作为切换变量 你可以用

来实现内联
<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>

每次单击链接,switch对象都会被一个新对象替换,其中只有正确的switch对象属性为true。未定义的属性将被赋值为false,因此依赖于它们的元素将不会被赋值为活动类。