AngularJS在为当前页面的链接设置一个活动类方面有任何帮助吗?
我想一定有什么神奇的方法可以做到,但我似乎找不到。
我的菜单是这样的:
<ul>
<li><a class="active" href="/tasks">Tasks</a>
<li><a href="/actions">Tasks</a>
</ul>
我在我的路由中为它们每个都有控制器:TasksController和ActionsController。
但是我想不出一种方法将a链接上的“活动”类绑定到控制器。
有提示吗?
我是这样做的:
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};
});
这可以让你在一个有跟踪活动指令的节中有链接:
<nav track-active>
<a href="#/">Page 1</a>
<a href="#/page2">Page 2</a>
<a href="#/page3">Page 3</a>
</nav>
在我看来,这种方法比其他方法干净得多。
此外,如果你使用的是jQuery,你可以让它更整洁,因为jQlite只有基本的选择器支持。在angular include之前包含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
使用指令(因为我们在这里做的是DOM操作),下面可能是最接近“angular方式”的方法:
$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>
也有同样的问题。以下是我的解决方案:
.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'
])
以上的指导性建议对我都没用。如果你有一个这样的引导导航栏
<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>
对我来说最重要的是不要更改引导的默认代码。
这是我的菜单控制器搜索菜单选项,然后添加我们想要的行为。
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>