Pregunta ¿Cuál es la mejor manera de aplicar una clase condicionalmente?


Digamos que tienes una matriz que se representa en un ul con un li para cada elemento y una propiedad en el controlador llamado selectedIndex. ¿Cuál sería la mejor manera de agregar una clase al li con el índice selectedIndex en AngularJS?

Actualmente estoy duplicando (a mano) el li codificar y agregar la clase a uno de los li etiquetas y usando ng-show y ng-hide para mostrar solo uno li por índice.


1132
2017-10-17 10:49


origen


Respuestas:


Si no quieres poner los nombres de las clases de CSS en Controller como yo, aquí hay un viejo truco que utilizo desde pre-v1 días. Podemos escribir una expresión que evalúa directamente a un nombre de clase seleccionado, no son necesarias directivas personalizadas:

ng:class="{true:'selected', false:''}[$index==selectedIndex]"

Tenga en cuenta la sintaxis antigua con dos puntos. 

También hay una nueva forma mejor de aplicar clases condicionalmente, como:

ng-class="{selected: $index==selectedIndex}"

Angular ahora admite expresiones que devuelven un objeto. Cada propiedad (nombre) de este objeto ahora se considera como un nombre de clase y se aplica según su valor.

Sin embargo, estas formas no son funcionalmente iguales. Aquí hay un ejemplo:

ng-class="{admin:'enabled', moderator:'disabled', '':'hidden'}[user.role]"

Por lo tanto, podríamos reutilizar las clases existentes de CSS asignando básicamente una propiedad de modelo a un nombre de clase y al mismo tiempo mantener las clases CSS fuera del código del Controlador.


1367
2017-11-29 11:17



clase ng admite una expresión que debe evaluar a cualquiera

  1. Una cadena de nombres de clase delimitados por espacios, o
  2. Una matriz de nombres de clase, o
  3. Un mapa / objeto de nombres de clase a valores booleanos.

Entonces, usando la forma 3) simplemente podemos escribir

ng-class="{'selected': $index==selectedIndex}"

Ver también ¿Cómo aplico condicionalmente estilos CSS en AngularJS? para una respuesta más amplia.


Actualizar: Angular 1.1.5 ha agregado soporte para operador ternario, entonces si ese constructo es más familiar para ti:

ng-class="($index==selectedIndex) ? 'selected' : ''"

432
2017-08-28 01:13



Mi método favorito es usar la expresión ternaria.

ng-class="condition ? 'trueClass' : 'falseClass'"

Nota: En caso de que esté usando una versión anterior de Angular, debería usar esto en su lugar,

ng-class="condition && 'trueClass' || 'falseClass'"

155
2017-09-27 13:39



Añadiré a esto, porque algunas de estas respuestas parecen desactualizadas. Así es como lo hago:

<class="ng-class:isSelected">

Donde 'isSelected' es una variable de javascript definida dentro del controlador angular de ámbito.


Para abordar su pregunta de manera más específica, esta es la forma en que puede generar una lista con eso:

HTML 

<div ng-controller="ListCtrl">  
    <li class="ng-class:item.isSelected" ng-repeat="item in list">   
       {{item.name}}
    </li>  
</div>


JS 

function ListCtrl($scope) {    
    $scope.list = [  
        {"name": "Item 1", "isSelected": "active"},  
        {"name": "Item 2", "isSelected": ""}
    ]
}


Ver: http://jsfiddle.net/tTfWM/

Ver: http://docs.angularjs.org/api/ng.directive:ngClass


53
2017-09-27 02:01



Aquí hay una solución mucho más simple:

function MyControl($scope){
    $scope.values = ["a","b","c","d","e","f"];
    $scope.selectedIndex = -1;
    
    $scope.toggleSelect = function(ind){
        if( ind === $scope.selectedIndex ){
            $scope.selectedIndex = -1;
        } else{
            $scope.selectedIndex = ind;
        }
    }
    
    $scope.getClass = function(ind){
        if( ind === $scope.selectedIndex ){
            return "selected";
        } else{
            return "";
        }
    }
       
    $scope.getButtonLabel = function(ind){
        if( ind === $scope.selectedIndex ){
            return "Deselect";
        } else{
            return "Select";
        }
    }
}
.selected {
    color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app ng-controller="MyControl">
    <ul>
        <li ng-class="getClass($index)" ng-repeat="value in values" >{{value}} <button ng-click="toggleSelect($index)">{{getButtonLabel($index)}}</button></li>
    </ul>
    <p>Selected: {{selectedIndex}}</p>
</div>


46
2017-10-17 13:55



Recientemente me enfrenté a un problema similar y decidí simplemente crear un filtro condicional:

  angular.module('myFilters', []).
    /**
     * "if" filter
     * Simple filter useful for conditionally applying CSS classes and decouple
     * view from controller 
     */
    filter('if', function() {
      return function(input, value) {
        if (typeof(input) === 'string') {
          input = [input, ''];
        }
        return value? input[0] : input[1];
      };
    });

Toma un solo argumento, que es una matriz de 2 elementos o una cadena, que se convierte en una matriz a la que se agrega una cadena vacía como segundo elemento:

<li ng-repeat="item in products | filter:search | orderBy:orderProp |
  page:pageNum:pageLength" ng-class="'opened'|if:isOpen(item)">
  ...
</li>

26
2017-07-26 07:53



Si desea ir más allá de la evaluación binaria y mantener su CSS fuera de su controlador, puede implementar un filtro simple que evalúe la entrada contra un objeto de mapa:

angular.module('myApp.filters, [])
  .filter('switch', function () { 
      return function (input, map) {
          return map[input] || '';
      }; 
  });

Esto le permite escribir su marcado de esta manera:

<div ng-class="muppets.star|switch:{'Kermit':'green', 'Miss Piggy': 'pink', 'Animal': 'loud'}">
    ...
</div>

21
2017-09-04 14:35



Operador ternario simplemente ha sido agregado al analizador angular en 1.1.5.

Entonces la forma más simple de hacer esto es ahora:

ng:class="($index==selectedIndex)? 'selected' : ''"

15
2018-05-23 08:32