agregar y eliminar clases en angularJs usando ng-click

97

Estoy tratando de trabajar cómo agregar una clase con ngClick. He cargado mi código en plunker Haga clic aquí . Mirando la documentación angular, no puedo averiguar la forma exacta en que debería hacerse. A continuación se muestra un fragmento de mi código. ¿Alguien puede guiarme en la dirección correcta?

 <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;
    });
Nuevo niño del vecindario
fuente
No queda claro en la demostración o explicación cuál es el objetivo. Parece estar tratando de alternar un menú, pero ¿por qué solo cambia el enlace del menú en la demostración?
charlietfl

Respuestas:

110

Solo necesita vincular una variable a la directiva "ng-class" y cambiarla desde el controlador. A continuación, se muestra un ejemplo de cómo hacer esto:

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>

Aquí está el ejemplo de trabajo en jsFiddle

geonunez
fuente
29
classes una palabra reservada, use classNameen su lugar, el compilador YUI fallará al minimizar esto.
Orlando
7
¿Qué pasa si quiero usar este código para más de un div en la misma vista? este código actuali cambia la clase para todos los div, cómo puedo aplicar la clase solo al elemento seleccionado en el que se hizo clic
xzegga
Gracias. Para comprender completamente lo que sucede cuando se hace clic en el botón Cambiar clase, abra la consola y vea el código.
fidev
1
Eche un vistazo a este hilo SO también. Es posible que no esté 100% vinculado con el alcance de la pregunta, pero aún así proporciona información útil adicional: stackoverflow.com/questions/31047094/…
BiLaL
144

Quiero agregar o eliminar laactive clase " " en mi código de forma dinámica ng-click, aquí lo que he hecho.

<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
fuente
13
-1 para ng-init. De acuerdo con los documentos de 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
Solo evito la parte del controlador "aquí", ya que esto es solo para mostrar la funcionalidad básica de cómo hacer eso ...
cutedevil086
1
También puede utilizar la sintaxis no documentada de `ng-class =" {'active': true} [selectedTab === 'users'] "`
Cody
No entiendo por qué esto funcionaría. Estoy haciendo algo muy similar en Angular 1.3.8 y la clase condicional no se elimina de un elemento cuando se hace clic en otro. Asumiría porque los otros elementos no se vuelven a renderizar. Entonces, ¿por qué funcionó esto alguna vez? ¿Las versiones anteriores de Angular reconstruyeron la lista completa cuando se hizo clic en un solo elemento?
Matt Molnar
Solo agrego esto porque puede ayudar a alguien más en el futuro. angular-ui-router tiene la funcionalidad que está especificando y mucho más. Creas estados que están representados por un uri. Cada estado puede tener 1 o más controladores, 1 o más plantillas y 1 o más vistas vinculadas a ellos. Los enlaces se generan utilizando la directiva ui-sref. La directiva ui-sref-active vinculará una clase específica a ese elemento cuando el estado esté activo. Documentación de Angular UI-Router
deadbabykitten
12

Hay una forma simple y limpia de hacer esto con solo directivas.

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

también puede hacer eso en una directiva, si desea eliminar la clase anterior y agregar una nueva clase

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

y en tu plantilla:

<i class="glyphicon glyphicon-pencil" toggle-class="glyphicon glyphicon-ok"></i>
Shilan
fuente
¿Por qué tiene los nombres de los iconos en la etiqueta y la directiva?
Robert Johnstone
Ese es un comentario tonto. Es algo perfectamente legítimo, aunque estoy de acuerdo en que tal vez no sea el lugar para hacerlo cuando explica cómo hacer algo en Angular
bert
¿Por qué no harías simplemente: angular.element ('glyphicon glyphicon-pencil) .removeClass (' glyphicon glyphicon-pencil ')? angular.element es prácticamente la versión jqLite de angular de $ en jquery. Podría simplemente crear un servicio o directiva que llame a esta función y pasar removeClasses y addedClasses en el constructor
MattE
Eso es cierto, pero estaba tratando de usar js angulares simples.
Shilan
7

Lo tiene exactamente bien, todo lo que tiene que hacer es establecer selectedIndex en su ng-click.

ng-click="selectedIndex = 1"

Así es como implementé un conjunto de botones que cambian la vista ng y resaltan el botón de la vista actualmente seleccionada.

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

y esto en mi controlador.

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

Usé la sugerencia de Zack Argyle anterior para obtener esto, que encuentro muy 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
fuente
2

Si prefiere la separación de preocupaciones de modo que la lógica para agregar y eliminar clases ocurra en el controlador, puede hacer esto

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

No puedo creer lo complejo que todo el mundo está haciendo esto. En realidad, esto es muy simple. Simplemente pegue esto en su html (no se requieren cambios de directive./controller - "bg-info" es una clase de arranque):

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

para formas reactivas -

Archivo HTML

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

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