Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS apply class to multiple buttons in mutual exclusive way

I'm new to AngularJS, with a jQuery background, and still trying to get into Angular thinking . I've several buttons like :

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

With jQuery to accomplish my goal, that is to have active class only on one button at time, I would do

jQuery

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

CSS

.active{ ... }

but I did not find out a general way to do this in Angular. I found a solution for 3 buttons, but it gets rude, especially if I have multiple route in my application.

In particular, now the solution I'm using is:

markup

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

In the CONTROLLER ( for bootstrap settings)

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

which is a solution that I don't really love, I don't think is a really good solution. Thanks in advance for helping.

jQuery solution Fiddle: http://jsfiddle.net/HS4d6/

like image 232
steo Avatar asked Dec 18 '13 14:12

steo


2 Answers

Welcome to Angular world -- it is bit different than jQuery. But you will love it!

There are a lot of goodies in Angular, but the queen among them is directive!

Here is a scaffold of solution that is quite generic and works without worrying about current scope at all. It basically uses directive initialization function to inter-instances communication. Just give me a shout if you have problems extending it to your particular needs.

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

like image 96
artur grzesiak Avatar answered Nov 19 '22 00:11

artur grzesiak


Since all your buttons seem to be very similar, you could use an ng-repeat like so:

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

And then your controller would be this:

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

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

It'd be easy to add more buttons this way and have them automatically work. Clearly modify to suit your own needs.

like image 2
Mathew Berg Avatar answered Nov 18 '22 23:11

Mathew Berg