Angular.js How to change an elements css class on click and to remove all others

Angularjs

Angularjs Problem Overview


i'm trying to make my two elements toggle, so if one element is clicked it will remove all references of my-class and apply it to its self. Any ideas?

<span id="1" ng-style="my-class" ng-click="tog=my-class"></span>

<span id="2" ng-style="my-class" ng-click="tog=my-class"></span>

Cheers!

Angularjs Solutions


Solution 1 - Angularjs

Create a scope property called selectedIndex, and an itemClicked function:

function MyController ($scope) {
  $scope.collection = ["Item 1", "Item 2"];

  $scope.selectedIndex = 0; // Whatever the default selected index is, use -1 for no selection

  $scope.itemClicked = function ($index) {
    $scope.selectedIndex = $index;
  };
}

Then my template would look something like this:

<div>
      <span ng-repeat="item in collection"
             ng-class="{ 'selected-class-name': $index == selectedIndex }"
             ng-click="itemClicked($index)"> {{ item }} </span>
</div>

Just for reference $index is a magic variable available within ng-repeat directives.

You can use this same sample within a directive and template as well.

Here is a working plnkr:

http://plnkr.co/edit/jOO8YdPiSJEaOcayEP1X?p=preview

Solution 2 - Angularjs

have you tried with a condition in ng-class like here : http://jsfiddle.net/DotDotDot/zvLvg/ ?

    <span id='1' ng-class='{"myclass":tog==1}' ng-click='tog=1'>span 1</span>
    <span id='2' ng-class='{"myclass":tog==2}' ng-click='tog=2'>span 2</span>

Solution 3 - Angularjs

To me it seems like the best solution is to use a directive; there's no need for the controller to know that the view is being updated.

Javascript:

var app = angular.module('app', ['directives']);

angular.module('directives', []).directive('toggleClass', function () {
    var directiveDefinitionObject = {
        restrict: 'A',
        template: '<span ng-click="localFunction()" ng-class="selected"  ng-transclude></span>',
        replace: true,
        scope: {
            model: '='
        },
        transclude: true,
        link: function (scope, element, attrs) {
            scope.localFunction = function () {
                scope.model.value = scope.$id;
            };
            scope.$watch('model.value', function () {
                // Is this set to my scope?
                if (scope.model.value === scope.$id) {
                    scope.selected = "active";
                } else {
                    // nope
                    scope.selected = '';
                }
            });
        }
    };
    return directiveDefinitionObject;
});

HTML:

<div ng-app="app" ng-init="model = { value: 'dsf'}"> <span>Click a span... then click another</span>

<br/>
<br/>
<span toggle-class model="model">span1</span>

<br/><span toggle-class model="model">span2</span>

<br/><span toggle-class model="model">span3</span>

CSS:

.active {
     color:red;
 }

I have a fiddle that demonstrates. The idea is when a directive is clicked, a function is called on the directive that sets a variable to the current scope id. Then each directive also watches the same value. If the scope ID's match, then the current element is set to be active using ng-class.

The reason to use directives, is that you no longer are dependent on a controller. In fact I don't have a controller at all (I do define a variable in the view named "model"). You can then reuse this directive anywhere in your project, not just on one controller.

Solution 4 - Angularjs

Typically with Angular you would be outputting these spans using the ngRepeat directive and (like in your case) each item would have an id. I know this is not true for all situations but it is typical if requesting data from a backend - objects in an array tend to have unique identifiers.

You can use this id to facilitate the toggling of classes on items in your list (see plunkr or code below).

Using the objects id's can also eliminate the undesirable effect when the $index (described in other answers) is messed up due to sorting in Angular.

Example Plunkr: http://plnkr.co/edit/na0gUec6cdMABK9L6drV

(basically apply the .active-selection class if the person.id is equal to $scope.activeClass - which we set when the user clicks an item.

Hope this helps someone, I've found expressions in ng-class to be very useful!

HTML

<ul>
  <li ng-repeat="person in people" 
  data-ng-class="{'active-selection': person.id == activeClass}">
    <a data-ng-click="selectPerson(person.id)">
      {{person.name}}
    </a>
  </li>
</ul>

JS

app.controller('MainCtrl', function($scope) {
  $scope.people = [{
    id: "1",
    name: "John",
  }, {
    id: "2",
    name: "Lucy"
  }, {
    id: "3",
    name: "Mark"
  }, {
    id: "4",
    name: "Sam"
  }];

  $scope.selectPerson = function(id) {
    $scope.activeClass = id;
    console.log(id);
  };
});    

CSS:

.active-selection {
  background-color: #eee;
}

Solution 5 - Angularjs

I only change/remove the class:

   function removeClass() {
                    var element = angular.element('#nameInput');
          element.removeClass('nameClass');
   };

Solution 6 - Angularjs

HTML

<span ng-class="{'item-text-wrap':viewMore}" ng-click="viewMore= !viewMore"></span>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTheNickyYoView Question on Stackoverflow
Solution 1 - AngularjsJesse EarleView Answer on Stackoverflow
Solution 2 - AngularjsDotDotDotView Answer on Stackoverflow
Solution 3 - AngularjspetebowdenView Answer on Stackoverflow
Solution 4 - AngularjsFlatSteveView Answer on Stackoverflow
Solution 5 - AngularjsDavid GonzalezView Answer on Stackoverflow
Solution 6 - AngularjsSantiago Rutales ThomazView Answer on Stackoverflow