adding and removing classes in angularJs using ng-click
Asked Answered
D

10

98

I am trying to work how to add a class with ngClick. I have uploaded up my code onto plunker Click here. Looking at the angular documentation i can't figure out the exact way it should be done. Below is a snippet of my code. Can someone guide me in the right direction

 <div ng-show="isVisible" ng-class="{'selected': $index==selectedIndex}" class="block"></div>

Controller

var app = angular.module("MyApp", []);
app.controller("subNavController", function ($scope){

        $scope.toggle = function (){
            $scope.isVisible = ! $scope.isVisible;
        };

        $scope.isVisible = false;
    });
Diploblastic answered 8/12, 2013 at 23:3 Comment(1)
not clear from demo or explnation what objective is. Seem to be trying to toggle a menu, but why aare you only toggling menu link in demo?Barnacle
G
110

You just need to bind a variable into the directive "ng-class" and change it from the controller. Here is an example of how to do this:

var app = angular.module("ap",[]);

app.controller("con",function($scope){
  $scope.class = "red";
  $scope.changeClass = function(){
    if ($scope.class === "red")
      $scope.class = "blue";
    else
      $scope.class = "red";
  };
});
.red{
  color:red;
}

.blue{
  color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="ap" ng-controller="con">
  <div ng-class="class">{{class}}</div>
  <button ng-click="changeClass()">Change Class</button>    
</body>

Here is the example working on jsFiddle

Goahead answered 8/12, 2013 at 23:41 Comment(4)
class is a reserved word, use className instead, YUI compiler will fail to minify this.Helm
What about if I want use this code for more than one div in the same view? this code actuali change class for all div, how I can apply class only to the selected clicked itemBackstitch
Thanks. To fully understand what is happening when the change Class button is clicked open the console and view the code.Circumference
Have a look at this SO thread also. Might not be 100% linked with the question scope but still provides extra useful information: #31047594Kragh
S
144

I want to add or remove "active" class in my code dynamically on ng-click, here what I have done.

<ul ng-init="selectedTab = 'users'">
   <li ng-class="{'active':selectedTab === 'users'}" ng-click="selectedTab = 'users'"><a href="#users" >Users</a></li>
   <li ng-class="{'active':selectedTab === 'items'}" ng-click="selectedTab = 'items'"><a href="#items" >Items</a></li>
</ul>
Sager answered 6/5, 2014 at 4:18 Comment(9)
-1 for ng-init. According to AngularJS docs - The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.Ran
I just avoiding the controller part "here", as this is just for showing the basic functionality of how to do that...Sager
You can also use the undocumented syntax of ` ng-class="{'active': true}[selectedTab === 'users']"`Book
I don't understand why this would work. I'm doing something very similar in Angular 1.3.8 and the conditional class is not removed from an element when another is clicked. I would assume because the other elements are not re-rendered. Why then, did this ever work? Did old versions of Angular re-build the entire list when a single element was clicked?Tonguelashing
I'm just adding this because it may help someone else down the line. angular-ui-router has the functionality you are specifying and much more. You create states which are represented by a uri. Each state may have 1 or more controllers, 1 or more templates, and 1 or more views bound to them. Links are generated using the ui-sref directive. The ui-sref-active directive will bind a specific class to that element when the state is active. Angular UI-Router DocumentationTimothea
I would declare seletedTab in controller.Tenon
@MikeGrabowski I guess the documentation was updated. It now says it can also be used for injecting data via server side scriptingWatkins
I think this answer is really awesome and I'm using this solution now, but I am not sure for a website that is going to have many tabs in different pages, if is solution the best? Because it can add more lines to DOM and it could be better if we use a functional way...Finespun
But on reloading the page, active class is set to the default element.Guyton
G
110

You just need to bind a variable into the directive "ng-class" and change it from the controller. Here is an example of how to do this:

var app = angular.module("ap",[]);

app.controller("con",function($scope){
  $scope.class = "red";
  $scope.changeClass = function(){
    if ($scope.class === "red")
      $scope.class = "blue";
    else
      $scope.class = "red";
  };
});
.red{
  color:red;
}

.blue{
  color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="ap" ng-controller="con">
  <div ng-class="class">{{class}}</div>
  <button ng-click="changeClass()">Change Class</button>    
</body>

Here is the example working on jsFiddle

Goahead answered 8/12, 2013 at 23:41 Comment(4)
class is a reserved word, use className instead, YUI compiler will fail to minify this.Helm
What about if I want use this code for more than one div in the same view? this code actuali change class for all div, how I can apply class only to the selected clicked itemBackstitch
Thanks. To fully understand what is happening when the change Class button is clicked open the console and view the code.Circumference
Have a look at this SO thread also. Might not be 100% linked with the question scope but still provides extra useful information: #31047594Kragh
A
12

There is a simple and clean way of doing this with only directives.

<div ng-class="{'class-name': clicked}" ng-click="clicked = !clicked"></div>
Asquith answered 4/8, 2016 at 2:50 Comment(0)
S
9

you can also do that in a directive, if you want to remove the previous class and add a new class

    .directive('toggleClass', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function() {
                if(element.attr("class") == "glyphicon glyphicon-pencil") {
                    element.removeClass("glyphicon glyphicon-pencil");
                    element.addClass(attrs.toggleClass);
                } else {
                    element.removeClass("glyphicon glyphicon-ok");
                    element.addClass("glyphicon glyphicon-pencil");
                }
            });
        }
    };
});

and in your template:

<i class="glyphicon glyphicon-pencil" toggle-class="glyphicon glyphicon-ok"></i>
Shackle answered 26/5, 2015 at 12:34 Comment(4)
why do you have the names of the icons in the tag and the directive?Establishment
That's a dumb comment. It's a perfectly legit thing to do although I agree that it's perhaps not the place for it when you're explaining how to do something in AngularMarron
why wouldn't you just do: angular.element('glyphicon glyphicon-pencil).removeClass('glyphicon glyphicon-pencil')? angular.element is pretty much angular's jqLite version of $ in jquery. You could just create a service or directive that calls this function and pass in removedClasses and addedClasses in the constructorForgat
That's true, but I was trying to use plain angular js.Shackle
D
7

You have it exactly right, all you have to do is set selectedIndex in your ng-click.

ng-click="selectedIndex = 1"

Here is how I implemented a set of buttons that change the ng-view, and highlights the button of the currently selected view.

<div id="sidebar" ng-init="partial = 'main'">
    <div class="routeBtn" ng-class="{selected:partial=='main'}" ng-click="router('main')"><span>Main</span></div>
    <div class="routeBtn" ng-class="{selected:partial=='view1'}" ng-click="router('view1')"><span>Resume</span></div>
    <div class="routeBtn" ng-class="{selected:partial=='view2'}" ng-click="router('view2')"><span>Code</span></div>
    <div class="routeBtn" ng-class="{selected:partial=='view3'}" ng-click="router('view3')"><span>Game</span></div>
  </div>

and this in my controller.

$scope.router = function(endpoint) {
    $location.path("/" + ($scope.partial = endpoint));
};
Datary answered 8/12, 2013 at 23:15 Comment(0)
N
4

var app = angular.module("MyApp", []);
app.controller("subNavController", function ($scope){

        $scope.toggle = function (){
            $scope.isVisible = ! $scope.isVisible;
        };

        $scope.isVisible = false;
    });
<div ng-show="isVisible" ng-class="{'active':isVisible}" class="block"></div>
Nonessential answered 17/2, 2016 at 9:20 Comment(0)
A
3

I used Zack Argyle's suggestion above to get this, which I find very elegant:

CSS:

.active {
    background-position: 0 -46px !important;
}

HTML:

<button ng-click="satisfaction = 'VeryHappy'" ng-class="{active:satisfaction == 'VeryHappy'}">
    <img src="images/VeryHappy.png" style="height:24px;" />
</button>
<button ng-click="satisfaction = 'Happy'" ng-class="{active:satisfaction == 'Happy'}">
    <img src="images/Happy.png" style="height:24px;" />
</button>
<button ng-click="satisfaction = 'Indifferent'" ng-class="{active:satisfaction == 'Indifferent'}">
    <img src="images/Indifferent.png" style="height:24px;" />
</button>
<button ng-click="satisfaction = 'Unhappy'" ng-class="{active:satisfaction == 'Unhappy'}">
    <img src="images/Unhappy.png" style="height:24px;" />
</button>
<button ng-click="satisfaction = 'VeryUnhappy'" ng-class="{active:satisfaction == 'VeryUnhappy'}">
    <img src="images/VeryUnhappy.png" style="height:24px;" />
</button>
Aardwolf answered 9/1, 2016 at 19:16 Comment(0)
E
2

If you prefer separation of concerns such that logic for adding and removing classes happens on the controller, you can do this

controller

 (function() {
    angular.module('MyApp', []).controller('MyController', MyController);

    function MyController() {
      var vm = this;
      vm.tab = 0;

      vm.setTab = function(val) {
          vm.tab = val;
       };
      vm.toggleClass = function(val) {
          return val === vm.tab;
           };
        }
    })();

HTML

<div ng-app="MyApp">
  <ul class="" ng-controller="MyController as myCtrl">
    <li ng-click="myCtrl.setTab(0)" ng-class="{'highlighted':myCtrl.toggleClass(0)}">One</li>
    <li ng-click="myCtrl.setTab(1)" ng-class="{'highlighted':myCtrl.toggleClass(1)}">Two</li>
    <li ng-click="myCtrl.setTab(2)" ng-class="{'highlighted':myCtrl.toggleClass(2)}">Three</li>
   <li ng-click="myCtrl.setTab(3)" ng-class="{'highlighted':myCtrl.toggleClass(3)}">Four</li>
 </ul>

CSS

.highlighted {
   background-color: green;
   color: white;
}
Estuarine answered 24/6, 2016 at 12:46 Comment(0)
A
0

I can't believe how complex everyone is making this. This is actually very simple. Just paste this into your html (no directive./controller changes required - "bg-info" is a bootstrap class):

<div class="form-group col-md-12">
    <div ng-class="{'bg-info':     (!transport_type)}"    ng-click="transport_type=false">CARS</div>
    <div ng-class="{'bg-info': transport_type=='TRAINS'}" ng-click="transport_type='TRAINS'">TRAINS</div>
    <div ng-class="{'bg-info': transport_type=='PLANES'}" ng-click="transport_type='PLANES'">PLANES</div>
</div>
Abeyance answered 3/11, 2016 at 14:53 Comment(0)
B
-1

for Reactive forms -

HTML file

<div class="col-sm-2">
  <button type="button"  [class]= "btn_class"  id="b1" (click)="changeMe()">{{ btn_label }}</button>
</div>

TS file

changeMe() {
  switch (this.btn_label) {
    case 'Yes ': this.btn_label = 'Custom' ;
    this.btn_class = 'btn btn-danger btn-lg btn-block';
    break;
    case 'Custom': this.btn_label = ' No ' ;
    this.btn_class = 'btn btn-success btn-lg btn-block';
    break;
    case ' No ': this.btn_label = 'Yes ';
      this.btn_class = 'btn btn-primary btn-lg btn-block';
      break;
  }
Biisk answered 12/6, 2018 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.