AngularJS将类应用于多个按钮,以互斥的方式。

6

我是一个刚接触AngularJS的初学者,具有jQuery背景,并且仍在努力理解“Angular思维”。 我有几个类似以下的

<button class="btn active">btn1</button>
<button class="btn">btn2</button>
...
<button class="btn">btnN</button>

使用 jQuery 来达成我的目标,即每次只有一个按钮拥有 active 类,我会这样做:

jQuery:

$(".btn").on('click', function(){
 $(this).siblings().removeClass('active')
        .end()
        .addClass('active');
});

CSS

.active{ ... }

但是我没有找到一种在Angular中通用的方法来实现这一点。我找到了一个解决方案,可以针对3个按钮,但它变得比较粗糙,特别是如果我的应用程序有多个route

特别是,现在我正在使用的解决方案是:

标记

<li class="start" ng:click="selected = 1" ng-class="{active: selected == 1}">
 <a href="#contenuti> </a>
</li>
<li class="start" ng:click="selected = 2" ng-class="{active: selected == 2}">
 <a href="#utenti> </a>
</li>
<li class="start" ng:click="selected = 3" ng-class="{active: selected == 3}">
 <a href="#messaggi> </a> 
</li>

在控制器中(用于引导设置)

switch($location.path()){
 case '/contenuti/plot': 
  $scope.selected = 1;
  break;
 case '/utenti': 
  $scope.selected = 2;
  break;
 case '/messaggi': 
  $scope.selected = 3;
  break;
}

这是一种解决方案,我并不是非常喜欢,我认为这不是一个真正好的解决方案。

jQuery 解决方案 Fiddle: http://jsfiddle.net/HS4d6/


AngularJS是数据驱动的。通常情况下,您应该忘记DOM。 - zs2020
2个回答

4

欢迎来到Angular世界--它与jQuery有些不同,但你会喜欢它!

在Angular中有许多好东西,但其中的王者就是directive

下面是一个相当通用的解决方案框架,它可以在不需要考虑当前作用域的情况下工作。它基本上使用指令初始化函数来实现实例间的通信。如果您在将其扩展到您的特定需求时遇到问题,请随时联系我。

app.directive('selectable', function(){

    var selected;

    var unselect = function(element) {
        element.removeClass('selected');
    }

    var select = function(element) {
        if (selected){
            unselect(selected);
        }
        selected = element;
        element.addClass('selected');
    }

    return {

        link : function(scope, element, attrs){

            element.on('click', function(){
                select(element);
            });

        }
    }
});

PLNKR


可以使用模型驱动的内容,您已将其移至指令并执行了类似于jQuery中所做的操作,我认为这不是Angular的方式。更好的方法是使用@Mathew建议的内容或用户已经在使用的内容。 - Chandermani
@Chandermani 按钮严格属于视图世界(DOM世界)- 你同意吗?我的解决方案只是一个脚手架,一颗种子 - 它应该作为灵感。它可以很容易地修改为模型驱动:只需通过“=”传递值进行$watch(或$observe“@”)。OP希望找到适用于以下情况的解决方案:特别是如果我在应用程序中有多个路由。您将如何在多个路由上使用ng-repeat - artur grzesiak
@Chandermani 还有一个问题:为什么使用jQuery选择器可能比这个更好 - 请提供一些上下文? - artur grzesiak
我认为这可能是一个有效的解决方案。我的想法是,如果它真的值得,与目标相比的代码行数并不那么“便宜”,我在思考是否有一种方法可以不使用jqlight DOM操作,实际上不使用on()而是使用ng-。无论如何,感谢您的所有解释和支持! - steo
@steo ng-click的工作方式几乎相同--它只是将回调附加到click事件。如果你想要触发一个动作,你可以通过在指令中设置selected=expression(在HTML标记中完全与ng-click一样)并在指令中返回:{link:...,scope:{selected: "&"}}。我不认为有那么多代码--此外,选择在恒定时间内运行,而您的jQuery解决方案需要O(按钮数量),而使用ng-repeat会在每个$digest周期重新运行,也需要线性时间。 - artur grzesiak
@arturgrzesiak,我在谈论他使用$scope.selected变量来选择活动元素。但是,我们可以使用更好的变量/对象来描述UI元素的上下文,而不是使用selected。 - Chandermani

2

由于您的所有按钮看起来非常相似,因此可以使用ng-repeat进行如下操作:

<li data-ng-repeat="button in buttons" data-ng-class="{ active: button.url == location.path() }></li>

然后你的控制器将是这样的:
function myController($scope....){
    $scope.location = $location;

    $scope.buttons = [
        { url: '/contenuti/plot' },
        { url: '/utenti' },
        { url: '/messaggi' }
    ];
}

通过这种方式添加更多的按钮并让它们自动工作将非常容易。请根据自己的需求进行修改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接