Jaki jest najlepszy sposób warunkowego zastosowania klasy?


1183

Załóżmy, że masz tablicę renderowaną ulza pomocą lidla każdego elementu i wywoływaną właściwość kontrolera selectedIndex. Jaki byłby najlepszy sposób dodania klasy liz indeksem selectedIndexw AngularJS?

Obecnie duplikuję (ręcznie) likod i dodaję klasę do jednego ze liznaczników oraz używam ng-showi ng-hidepokazuję tylko jeden lina indeks.


2
Odpowiedzi na to pytanie pokazują, że w szablonie jest coś więcej niż {{varname}}. Gdzie mogę znaleźć dokumentację tego, co jeszcze jest do szablonów, na przykład operator trójskładnikowy w kilku różnych formach? docs.quarejs.org/guide/templates wydaje się nie wyjaśniać, co oferuje szablony pod względem warunków warunkowych itp. oprócz {{nazwa_nazwy_fielda}}.
Christos Hayward

jest to dla mnie tak przydatne, mam nadzieję, że to zadziała dla ciebie tech-blog.maddyzone.com/javascript/…
Rituraj ratan

Odpowiedzi:


1384

Jeśli nie chcesz wstawiać nazw klas CSS do kontrolera tak jak ja, oto stara sztuczka, której używam od dni wcześniejszych niż v1. Możemy napisać wyrażenie, które ocenia bezpośrednio do wybranej nazwy klasy , nie są wymagane żadne niestandardowe dyrektywy:

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

Zwróć uwagę na starą składnię z dwukropkiem.

Istnieje również nowy lepszy sposób warunkowego stosowania klas, na przykład:

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

Angular obsługuje teraz wyrażenia zwracające obiekt. Każda właściwość (nazwa) tego obiektu jest teraz uważana za nazwę klasy i jest stosowana w zależności od jej wartości.

Jednak te sposoby nie są funkcjonalnie równe. Oto przykład:

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

W związku z tym moglibyśmy ponownie wykorzystać istniejące klasy CSS, zasadniczo odwzorowując właściwość modelu na nazwę klasy i jednocześnie utrzymując klasy CSS poza kodem kontrolera.


33
OP, to może być najgorszy sposób wyrażenia operatora trójskładnikowego, jaki kiedykolwiek widziałem. Czy zastanawiałeś się ($index==selectedIndex) ? 'selected' : ''?
Malvolio

17
@Malvolio AFAIR, operator trójskładnikowy nie działał w wyrażeniach kątowych w wersji 0.9.x. To mniej więcej zmiana.
orcun

36
ng-klasa (stan na 19.01.2012) obsługuje teraz wyrażenie, które musi oceniać, aby 1) ciąg nazw klas rozdzielonych spacjami lub 2) i tablica nazw klas, lub 3) mapa / obiekt klasy nazwy wartości boolowskich. Tak więc, używając 3): ng-class = "{selected: $ index == selectedIndex}"
Mark Rajcok

2
Dzięki @Mark, BTW teraz, kiedy sprawdziłem, mogę powiedzieć, że ta metoda działa w v1. W niektórych przypadkach nadal jest przydatny. Zauważ, że nazwy właściwości obiektów (klucze) niekoniecznie są prawdziwe lub fałszywe, może to być wszystko, co możesz chcieć odwzorować na nazwę klasy.
orcun,

6
Chcę tylko dodać, że miałem problem, ponieważ użyłem składni jak {classname: '$index === selectedIndex'} i to nie działało. Kiedy położyłem wszystko razem i użyłem == zamiast === zadziałało. {classname: '$index==selectedIndex'}
Lucas

437

Klasa ng obsługuje wyrażenie, które musi być ocenione jako jedno z nich

  1. Ciąg nazw klas rozdzielanych spacjami lub
  2. Tablica nazw klas lub
  3. Mapa / obiekt nazw klas na wartości boolowskie.

Korzystając z formularza 3), możemy po prostu pisać

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

Zobacz także Jak warunkowo zastosować style CSS w AngularJS? dla szerszej odpowiedzi.


Aktualizacja : Angular 1.1.5 dodał obsługę trójskładnikowego operatora , więc jeśli ta konstrukcja jest ci bardziej znana:

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

2
+1 dla operatorów trójskładnikowych (a teraz potrzebuję jednego), ale 1.1. * To „niestabilna wersja”, w której interfejs API może ulec zmianie bez uprzedzenia - w momencie pisania. Wersja 1.0. * Jest stabilna, więc wygodniej byłoby z tym zrobić projekt, który będzie realizowany w przyszłym tygodniu przez 6 miesięcy.
Dave Everitt

1
ng-class="{'selected': $index==selectedIndex}"działa dla mnie
knuhol

160

Moją ulubioną metodą jest użycie wyrażenia trójskładnikowego.

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

Uwaga: jeśli używasz starszej wersji Angulara, powinieneś użyć jej zamiast tego,

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

2
To pomogło mi pisanie tego wyrażenia: ng-class="property.name=='timestamp' ? 'property-timestamp' : 'property-'+{{$index}}". Nie udało mi się wymyślić żadnego innego sposobu.
dduft

Naprawdę nie znajduję powodu, dla którego moja zmienna logiczna modalFlag nie aktualizuje się - ng-class = "{'closed': modalFlag, 'open':! ModalFlag}" Próbuję dodać zamknięty lub otwarty w zależności od zmiennej zakresu / boolean - jeśli ktoś mógłby pomóc, byłbym bardzo wdzięczny - dziękuję.
wylądował

Zostało to wprowadzone w wersji 1.5. github.com/angular/angular.js/commit/…
Mubashir Koul

55

Dodam do tego, ponieważ niektóre z tych odpowiedzi wydają się nieaktualne. Oto jak to robię:

<class="ng-class:isSelected">

Gdzie „isSelected” to zmienna javascript zdefiniowana w obrębie kontrolera kątowego o zasięgu.


Aby dokładniej odpowiedzieć na twoje pytanie, oto jak możesz wygenerować listę z tym:

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": ""}
    ]
}


Zobacz: http://jsfiddle.net/tTfWM/

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


Czym różni się class = "ng-class: item.isSelected" i ng-class = "item.isSelected"
zloctb

Ciekawi Cię użycie ng-class:classNamevs po prostu class="{{className}}"?
Roi

48

Oto o wiele prostsze rozwiązanie:

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>


74
Gorąco polecam, aby trzymać twój kontroler z dala od CSS. To ścieżka, której nie chcesz schodzić.
leviathan

1
Nazwy klas należą do szablonu
Casey

5
W pewnym momencie jsfiddle może spóźnić się z opłaceniem rachunków lub przenieść się do innej domeny, albo odpowiedzialni ludzie zostaną zabici przez autobus (patrz także Bus Factor). Więc czy mogę prosić o wyjaśnienie, co robi to skrzypce, w twojej odpowiedzi? Jest to również kanoniczne w przypadku przepełnienia stosu.
Sebastian Mach

27

Ostatnio napotkałem podobny problem i postanowiłem po prostu utworzyć filtr warunkowy:

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

Pobiera pojedynczy argument, którym jest albo 2-elementowa tablica, albo ciąg, który zamienia się w tablicę, do której dołączany jest pusty ciąg jako drugi element:

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

1
me to właśnie utworzyłem na przykład filtr yesNo () zwracający klasy „tak” lub „nie” zgodnie z wartością logiczną 1 o 0: filter('yesNo', function() { return function(input) { // info('yesNo('+ input +')'); switch(input){ case '1': return ' yes '; break; default: return ' no '; break; } } });
svassr

1
ng-class może obsługiwać mapę / obiekt nazw klas do wartości boolowskich, więc możesz po prostu napisać: ng-class = "{tak: some_boolean_expression, no: some_other_boolean_expression}" Np. ng-class = "{yes: input , brak wejścia}"
:!

21

Jeśli chcesz wyjść poza ocenę binarną i trzymać CSS z dala od kontrolera, możesz zaimplementować prosty filtr, który ocenia dane wejściowe względem obiektu mapy:

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

Pozwala to napisać znaczniki w następujący sposób:

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

Cześć @Joe, jakieś pomysły na obsługę wartości zerowych? Jeśli
podam

1
@ użytkownik1191559 - możesz „domyślny” element mapy, a następnie zwrócić tę wartość, jeśli „dane wejściowe” są puste.
Joe Steele,

17

Ostatnio robiłem to tak:

<input type="password"  placeholder="Enter your password"
ng-class="{true: 'form-control isActive', false: 'isNotActive'}[isShowing]">

The isShowingWartość jest to wartość, która znajduje się na moim kontroler, który pobiera z przełączanych za pomocą kliknięcia jednego przycisku i części pomiędzy pojedynczym nawiasie są klasy I utworzone w moim pliku css.

EDYCJA: Chciałbym również dodać, że codechool.com ma bezpłatny kurs sponsorowany przez Google na AngularJS, który omawia wszystkie te rzeczy, a potem niektóre. Za nic nie trzeba płacić, wystarczy założyć konto i zacząć! Powodzenia wszystkim!


Czy mógłbyś podać tutaj skrzypce lub więcej kodów? Czy isShowingzatem tablica w kontrolerze?
Kyle Pennell,

Chyba boolean
Mirko

15

Operator trójskładnikowy został właśnie dodany do parsera kątowego w 1.1.5 .

Najprostszym sposobem na zrobienie tego jest teraz:

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

Również: class="otherClass ng-class:($index==selectedIndex)? 'selected' : '';".
Peter

11

Możemy stworzyć funkcję zarządzania klasą zwrotu z warunkiem

wprowadź opis zdjęcia tutaj

<script>
    angular.module('myapp', [])
            .controller('ExampleController', ['$scope', function ($scope) {
                $scope.MyColors = ['It is Red', 'It is Yellow', 'It is Blue', 'It is Green', 'It is Gray'];
                $scope.getClass = function (strValue) {
                    switch(strValue) {
                        case "It is Red":return "Red";break;
                        case "It is Yellow":return "Yellow";break;
                        case "It is Blue":return "Blue";break;
                        case "It is Green":return "Green";break;
                        case "It is Gray":return "Gray";break;
                    }
                }
        }]);
</script>

I wtedy

<body ng-app="myapp" ng-controller="ExampleController">

<h2>AngularJS ng-class if example</h2>
<ul >
    <li ng-repeat="icolor in MyColors" >
        <p ng-class="[getClass(icolor), 'b']">{{icolor}}</p>
    </li>
</ul>
<hr/>
<p>Other way using : ng-class="{'class1' : expression1, 'class2' : expression2,'class3':expression2,...}"</p>
<ul>
    <li ng-repeat="icolor in MyColors">
        <p ng-class="{'Red':icolor=='It is Red','Yellow':icolor=='It is Yellow','Blue':icolor=='It is Blue','Green':icolor=='It is Green','Gray':icolor=='It is Gray'}" class="b">{{icolor}}</p>
    </li>
</ul>

Możesz odwołać się do pełnej strony kodowej na ng-class, jeśli przykład


9

Jestem nowy w Angular, ale znalazłem to, aby rozwiązać mój problem:

<i class="icon-download" ng-click="showDetails = ! showDetails" ng-class="{'icon-upload': showDetails}"></i>

To warunkowo zastosuje klasę opartą na var. Zaczyna się od domyślnego pobrania ikony , używając klasy ng, sprawdzam status showDetailsif true/falsei stosuję przesyłanie ikon klasy . Działa świetnie.

Mam nadzieję, że to pomoże.


9

To działa jak urok;)

<ul class="nav nav-pills" ng-init="selectedType = 'return'">
    <li role="presentation" ng-class="{'active':selectedType === 'return'}"
        ng-click="selectedType = 'return'"><a href="#return">return

    </a></li>
    <li role="presentation" ng-class="{'active':selectedType === 'oneway'}"
        ng-click="selectedType = 'oneway'"><a href="#oneway">oneway
    </a></li>
</ul>

5

Prawdopodobnie przejdzie to do zapomnienia, ale oto jak wykorzystałem trójskładnikowe operatory 1.1.5 do przełączania klas w zależności od tego, czy wiersz w tabeli jest pierwszym, środkowym czy ostatnim - z wyjątkiem tego, że w tabeli jest tylko jeden wiersz:

<span class="attribute-row" ng-class="(restaurant.Attributes.length === 1) || ($first ? 'attribute-first-row': false || $middle ? 'attribute-middle-row': false || $last ? 'attribute-last-row': false)">
</span>

5

To jest w mojej pracy wielu warunkowo ocenić:

<li ng-repeat='eOption in exam.examOptions' ng-class="exam.examTitle.ANSWER_COM==exam.examTitle.RIGHT_ANSWER?(eOption.eoSequence==exam.examTitle.ANSWER_COM?'right':''):eOption.eoSequence==exam.examTitle.ANSWER_COM?'wrong':eOption.eoSequence==exam.examTitle.RIGHT_ANSWER?'right':''">
  <strong>{{eOption.eoSequence}}</strong> &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
  <span ng-bind-html="eOption.eoName | to_trusted">2020 元</span>
</li>

4

Oto kolejna opcja, która działa dobrze, gdy nie można użyć klasy ng (na przykład podczas stylowania SVG):

ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"

(Myślę, że musisz używać najnowszego niestabilnego Angulara, aby używać ng-attr-, aktualnie jestem na wersji 1.1.4)


4

cóż, sugerowałbym sprawdzenie stanu w kontrolerze za pomocą funkcji zwracającej wartość prawda lub fałsz .

<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>

i sprawdź w swoim kontrolerze

$scope.getTodayForHighLight = function(today, date){
return (today == date);
}

4

częściowy

  <div class="col-md-4 text-right">
      <a ng-class="campaign_range === 'thismonth' ? 'btn btn-blue' :  'btn btn-link'" href="#" ng-click='change_range("thismonth")'>This Month</a>
      <a ng-class="campaign_range === 'all' ? 'btn btn-blue' :  'btn btn-link'" href="#" ng-click='change_range("all")'>All Time</a>
  </div>

kontroler

  $scope.campaign_range = "all";
  $scope.change_range = function(range) { 
        if (range === "all")
        {
            $scope.campaign_range = "all"
        }
        else
        {  
            $scope.campaign_range = "thismonth"
        }
  };

3

Jeśli używasz kątowego wcześniejszej niż 1.1.5 (tzn. Nie ma operatora trójskładnikowego) i nadal potrzebujesz równoważnego sposobu ustawienia wartości w obu warunkach, możesz zrobić coś takiego:

ng-class="{'class1':item.isReadOnly == false, 'class2':item.isReadOnly == true}"

3

Jeśli masz wspólną klasę stosowaną do wielu elementów, możesz utworzyć niestandardową dyrektywę, która doda tę klasę, np. Ng-show / ng-hide.

Ta dyrektywa doda klasę „aktywną” do przycisku, jeśli zostanie kliknięty

module.directive('ngActive',  ['$animate', function($animate) {
  return function(scope, element, attr) {
    scope.$watch(attr.ngActive, function ngActiveWatchAction(value){
      $animate[value ? 'addClass' : 'removeClass'](element, 'active');
    });
  };
}]);

Więcej informacji



3

Sprawdź to .

Niesławne if|elseoświadczenie AngularJS !!!
Kiedy zacząłem używać Angularjs, byłem trochę zaskoczony, że nie mogłem znaleźć instrukcji if / else.

Pracowałem więc nad projektem i zauważyłem, że podczas używania instrukcji if / else warunek pojawia się podczas ładowania. Aby to naprawić, możesz użyć ng-cloak.

<div class="ng-cloak">
 <p ng-show="statement">Show this line</span>
 <p ng-hide="statement">Show this line instead</span>
</div>

.ng-cloak { display: none }

Dzięki, amadou


0

Możesz użyć tego pakietu npm. Obsługuje wszystko i ma opcje dla klas statycznych i warunkowych opartych na zmiennej lub funkcji.

// Support for string arguments
getClassNames('class1', 'class2');

// support for Object
getClassNames({class1: true, class2 : false});

// support for all type of data
getClassNames('class1', 'class2', ['class3', 'class4'], { 
    class5 : function() { return false; },
    class6 : function() { return true; }
});

<div className={getClassNames({class1: true, class2 : false})} />
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.