[英]Applying css class depending on subelements
我想根据子元素是否符合特定条件将css类设置为列表项。 结构类似于以下示例:
<ul ng-controller="Navigation">
<li><a href="#">Category A</a>
<ul>
<li><a href="a1.html">a1</a></li>
<li><a href="a2.html">a2</a></li>
</ul>
</li>
<li><a href="#">Category B</a>
<ul>
<li><a href="b1.html">b1</a></li>
<li><a href="b2.html">b2</a></li>
</ul>
</li>
<li><a href="contact.html">contact</a></li>
</ul>
我的模型是当前页面,例如a2.html
。 如果链接具有与模型值相同的href
属性,则它应具有某个css类( active
)。 这可以用以下表达式完成:
<a href="a1.html" ng-class="{'active': currentPage == 'a1.html'}>
但这有点不a1.html
,因为我必须重复文件名( a1.html
)。 是否可以将当前元素传递给函数? 像这样: ng-class="getClass(currentElement)"
下一个问题是,我想根据子级是否active
该类来选择父级元素。 如果在我上面的示例中选择了<a href="a1.html">a1</a>
,则Category A
应使该类active
。
结论
'stewie的解决方案有效,但是我得出的结论是Angular并不是完成这项工作的最佳工具。 它不是Web“应用程序”(Angular的域),而是静态html,应该对其进行丰富。
这个简单的jQuery代码段可以完成这项工作:
var activeLink = $("a").filter(function() {
return $(this).attr("href") == currentPage();
});
activeLink.addClass("active");
activeLink.parents("li").children("a").addClass("active");
可以通过在UL元素上使用自定义指令来完成此操作,该指令将在模型更改时遍历列表,并在匹配项上设置适当的“活动”类。 请以此柱塞为例 。 请注意,该指令可以进一步优化。 这只是一个示范。
HTML:
<ul menu ng-controller="Navigation">
<li><a href="#">Category A</a>
<ul>
<li><a href="a1.html">a1</a></li>
<li><a href="a2.html">a2</a></li>
</ul>
</li>
<li><a href="#">Category B</a>
<ul>
<li><a href="b1.html">b1</a></li>
<li><a href="b2.html">b2</a></li>
</ul>
</li>
<li><a href="contact.html">contact</a></li>
</ul>
JS:
var app = angular.module('plunker', []);
app.controller('Navigation',
function($scope) {}
);
app.directive('menu',
function(){
return {
link: function ($scope, $element) {
var link, li;
$scope.$watch('currentPage', function(page){
activate(page);
});
function activate(page){
angular.forEach($element.find('li'), function(elm){
li = angular.element(elm);
link = li.find('a');
if(link.attr('href') === $scope.currentPage){
li.addClass('active');
li.parents('li').addClass('active');
return;
}
li.removeClass('active');
});
}
}
};
}
);
我看了@Stewei的解决方案。 但是,为此使用指令编写解决方案对我来说毫无意义。 我认为,仅在创建组件时或在冲压模板时才应编写指令。 即使是为了淘汰模板,我也建议人们使用ng-include或类似的东西,除非您想要自定义元素提供的语义。
但是,我相信执行此操作的Angular方法是将行为逻辑与“特定于应用程序”的逻辑完全分开。 我认为您编写指令的方式应使其独立于周围的控制器。
这是一个实际上可以解决此问题的工具,希望能以最“角度的方式”解决。 如果您可以对所有链接使用某种数据模型,并且可能对该模型进行ng-repeat,则可以进一步分离。 但这是开发人员的选择。 由于您提到的是静态页面,因此此解决方案可能最适合。
http://plnkr.co/edit/DjaYi1ofpFKgKfhtakub?p=preview
在您最初的问题中,您确实询问过是否可以将currentElement传递给getClass方法。 我之前曾问过这个问题,答案是否定的。 可以传递对currentElement的引用的唯一地方是在指令控制器中,但是目前这不在主题范围内。
这是完成手头任务的代码。
HTML:
<div ng-controller="NavController">
<ul >
<li ng-class="getCategoryClass('A')">
<a href="#">Category A</a>
<ul>
<li ng-class="getClass('a1.html','A')"><a href="a1.html">a1</a></li>
<li ng-class="getClass('a2.html','A')"><a href="a2.html">a2</a></li>
</ul>
</li>
<li ng-class="getCategoryClass('B')">
<a href="#">Category B</a>
<ul>
<li ng-class="getClass('b1.html','B')"><a href="b1.html">b1</a></li>
<li ng-class="getClass('b2.html','B')"><a href="b2.html">b2</a></li>
</ul>
</li>
<li ng-class="getClass('contact.html','contact')"><a href="contact.html">contact</a></li>
</ul>
<input ng-model="currentPage" />
<br>
currentPage: {{currentPage}}
</div>
JS:
app.controller('NavController',
function($scope) {
$scope.currentPage = "";
$scope.currentCategory = "";
$scope.pageActive = false;
$scope.getClass = function(page,category){
if( page === $scope.currentPage ) {
$scope.pageActive = true;
$scope.currentCategory = category;
return "active";
}
else{
return "";
}
};
$scope.$watch('currentPage',function(val){
$scope.pageActive = false;
});
$scope.onLinkClick = function($event){
$event.preventDefault();
};
$scope.getCategoryClass = function(category){
return $scope.currentCategory === category && $scope.pageActive ? "active" : "";
};
}
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.