adicionar e remover classes em angularJs usando ng-click

97

Estou tentando trabalhar como adicionar uma classe com ngClick. Eu carreguei meu código no plunker Clique aqui . Olhando para a documentação angular, não consigo descobrir a maneira exata como isso deve ser feito. Abaixo está um trecho do meu código. Alguém pode me guiar na direção certa

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

Controlador

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

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

        $scope.isVisible = false;
    });
Novo garoto no quarteirão
fonte
não está claro na demonstração ou explicação qual é o objetivo. Parece estar tentando alternar um menu, mas por que você só alterna o link do menu na demonstração?
charlietfl

Respostas:

110

Você só precisa vincular uma variável à diretiva "ng-class" e alterá-la no controlador. Aqui está um exemplo de como fazer isso:

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>

Aqui está o exemplo trabalhando em jsFiddle

Geonunez
fonte
29
classé uma palavra reservada, use em classNamevez disso, o compilador YUI não conseguirá reduzir isso.
Orlando
7
E se eu quiser usar este código para mais de um div na mesma visualização? este código altera a classe para todos os div, como posso aplicar a classe apenas ao item selecionado clicado
xzegga
Obrigado. Para entender completamente o que está acontecendo quando o botão Alterar Classe é clicado, abra o console e visualize o código.
fidev
1
Dê uma olhada neste tópico do SO também. Pode não estar 100% vinculado ao escopo da pergunta, mas ainda fornece informações úteis adicionais: stackoverflow.com/questions/31047094/…
BiLaL
144

Desejo adicionar ou remover aactive classe " " no meu código dinamicamente ng-click, aqui está o que eu fiz.

<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>
cutedevil086
fonte
13
-1 para ng-init. De acordo com os documentos do AngularJS -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.
Mike Grabowski
2
Estou apenas evitando a parte do controlador "aqui", pois isso é apenas para mostrar a funcionalidade básica de como fazer isso ...
cutedevil086
1
Você também pode usar a sintaxe não documentada de `ng-class =" {'active': true} [selectedTab === 'users'] "`
Cody
Eu não entendo por que isso funcionaria. Estou fazendo algo muito semelhante no Angular 1.3.8 e a classe condicional não é removida de um elemento quando outro é clicado. Eu presumiria porque os outros elementos não são renderizados novamente. Por que então isso funcionou? As versões antigas do Angular reconstruíram a lista inteira quando um único elemento foi clicado?
Matt Molnar
Estou apenas adicionando isso porque pode ajudar outra pessoa no processo. angular-ui-router tem a funcionalidade que você está especificando e muito mais. Você cria estados que são representados por um uri. Cada estado pode ter 1 ou mais controladores, 1 ou mais modelos e 1 ou mais visualizações vinculadas a eles. Os links são gerados usando a diretiva ui-sref. A diretiva ui-sref-active vinculará uma classe específica a esse elemento quando o estado estiver ativo. Documentação Angular UI-Router
deadbabykitten
12

Existe uma maneira simples e limpa de fazer isso apenas com diretivas.

<div ng-class="{'class-name': clicked}" ng-click="clicked = !clicked"></div>
Artecher
fonte
8

você também pode fazer isso em uma diretiva, se quiser remover a classe anterior e adicionar uma nova classe

    .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");
                }
            });
        }
    };
});

e em seu modelo:

<i class="glyphicon glyphicon-pencil" toggle-class="glyphicon glyphicon-ok"></i>
Shilan
fonte
por que você tem os nomes dos ícones na tag e na diretiva?
Robert Johnstone
Esse é um comentário idiota. É uma coisa perfeitamente legítima de se fazer, embora eu concorde que talvez não seja o lugar para isso quando você estiver explicando como fazer algo em Angular
bert
por que você simplesmente não faria: angular.element ('glyphicon glyphicon-pencil) .removeClass (' glyphicon glyphicon-pencil ')? angular.element é basicamente a versão jqLite do angular de $ no jquery. Você poderia apenas criar um serviço ou diretiva que chame esta função e passar removedClasses e addedClasses no construtor
MattE
É verdade, mas eu estava tentando usar o js angular simples.
Shilan 01 de
7

Você acertou exatamente, tudo o que você precisa fazer é definir o selectedIndex no seu ng-click.

ng-click="selectedIndex = 1"

Aqui está como eu implementei um conjunto de botões que mudam a visualização do ng e destaca o botão da visualização atualmente selecionada.

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

e isso no meu controlador.

$scope.router = function(endpoint) {
    $location.path("/" + ($scope.partial = endpoint));
};
Zack Argyle
fonte
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>

Jay Prakash Singh
fonte
2

Usei a sugestão de Zack Argyle acima para conseguir isso, que considero muito elegante:

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>
Adriaan Davel
fonte
2

Se você preferir a separação de interesses de forma que a lógica para adicionar e remover classes aconteça no controlador, você pode fazer isso

controlador

 (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;
}
Dennis Wanyonyi
fonte
-1

Não posso acreditar como todo mundo está tornando isso complexo. Na verdade, isso é muito simples. Apenas cole isso em seu html (não são necessárias alterações de diretiva./controlador - "bg-info" é uma classe de bootstrap):

<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>
john pallot
fonte
-1

para formas reativas -

Arquivo HTML

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

Arquivo TS

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

M Singh
fonte