javascript - AngularJS aplicar classe a múltiplos botões de forma mutuamente exclusiva


Sou novo em AngularJS, com experiência em jQuery, e ainda estou a tentar entrar no modo de pensar Angular. Tenho vários buttons como:

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

Com jQuery para alcançar o meu objetivo, que é ter a classe active apenas num button de cada vez, eu faria

jQuery

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

CSS

.active{ ... }

mas eu não descobri uma forma geral de fazer isto no Angular. Encontrei uma solução para 3 botões, mas torna-se complicada, especialmente se eu tiver múltiplas route na minha aplicação.

Em particular, agora a solução que estou a usar é:

marcação

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

NO CONTROLADOR (para definições do bootstrap)

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

que é uma solução que eu realmente não gosto, não acho que seja uma solução realmente boa. Obrigado desde já pela ajuda.

Solução jQuery Fiddle: http://jsfiddle.net/HS4d6/

Resposta #1

Bem-vindo ao mundo Angular -- é um pouco diferente do jQuery. Mas vai adorar!

Existem muitas coisas boas no Angular, mas a rainha entre elas é directive!

Aqui está uma estrutura de solução que é bastante genérica e funciona sem se preocupar com o âmbito atual de todo. Basicamente, utiliza a função de inicialização da diretiva para a comunicação entre instâncias. Apenas dê-me um toque se tiver problemas em adaptá-la às suas necessidades particulares.

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

Resposta #2

Como todos os seus botões parecem ser muito semelhantes, você poderia usar um ng-repeat assim:

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

E então o seu controlador seria este:

function myController($scope....){
    $scope.location = $location;

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

Seria fácil adicionar mais botões desta forma e fazê-los funcionar automaticamente. Modifique claramente para se adequar às suas próprias necessidades.