Was ist der beste Weg, um eine Klasse bedingt anzuwenden?


1183

Nehmen wir an, Sie haben ein Array, das in a ulmit einem lifür jedes Element und einer Eigenschaft auf dem aufgerufenen Controller gerendert wird selectedIndex. Was wäre der beste Weg, um lidem Index selectedIndexin AngularJS eine Klasse hinzuzufügen ?

Ich dupliziere derzeit (von Hand) den liCode und füge die Klasse einem der liTags hinzu und verwende ng-showund ng-hidezeige nur eine lipro Index.


2
Antworten auf diese Frage zeigen, dass das Templating mehr enthält als {{varname}}. Wo finde ich eine Dokumentation darüber, was das Templating noch zu bieten hat, z. B. den ternären Operator in verschiedenen Formen? docs.angularjs.org/guide/templates scheint nicht zu erklären, was Templating in Bezug auf Bedingungen usw. außer {{varname.fieldname}} bietet.
Christos Hayward

Das ist so nützlich für mich. Ich hoffe, es wird für Sie funktionieren. tech-blog.maddyzone.com/javascript/…
Rituraj ratan

Antworten:


1384

Wenn Sie CSS-Klassennamen nicht wie ich in Controller einfügen möchten, finden Sie hier einen alten Trick, den ich seit Tagen vor Version 1 verwende. Wir können einen Ausdruck schreiben, der direkt zu einem ausgewählten Klassennamen ausgewertet wird. Es sind keine benutzerdefinierten Anweisungen erforderlich:

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

Bitte beachten Sie die alte Syntax mit Doppelpunkt.

Es gibt auch eine neue bessere Möglichkeit, Klassen bedingt anzuwenden, wie zum Beispiel:

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

Angular unterstützt jetzt Ausdrücke, die ein Objekt zurückgeben. Jede Eigenschaft (Name) dieses Objekts wird jetzt als Klassenname betrachtet und abhängig von ihrem Wert angewendet.

Diese Wege sind jedoch funktional nicht gleich. Hier ist ein Beispiel:

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

Wir könnten daher vorhandene CSS-Klassen wiederverwenden, indem wir eine Modelleigenschaft grundsätzlich einem Klassennamen zuordnen und gleichzeitig CSS-Klassen aus dem Controller-Code heraushalten.


33
OP, das ist vielleicht der schlechtere Weg, um den ternären Operator auszudrücken, den ich je gesehen habe. Hast du darüber nachgedacht ($index==selectedIndex) ? 'selected' : ''?
Malvolio

17
@Malvolio AFAIR, ternärer Operator arbeitete in v0.9.x nicht innerhalb von Winkelausdrücken. Dies ist mehr oder weniger ein Schalter.
Orcun

36
ng-class (Stand 19.01.2012) unterstützt jetzt einen Ausdruck, der entweder 1) eine Zeichenfolge von durch Leerzeichen getrennten Klassennamen oder 2) ein Array von Klassennamen oder 3) eine Karte / ein Objekt der Klasse ergeben muss Namen zu booleschen Werten. Also, mit 3): ng-class = "{selected: $ index == selectedIndex}"
Mark Rajcok

2
Danke @Mark, übrigens, nachdem ich überprüft habe, kann ich sagen, dass diese Methode in Version 1 funktioniert. In einigen Fällen ist es immer noch nützlich. Beachten Sie, dass Objekteigenschaftsnamen (Schlüssel) nicht unbedingt wahr oder falsch sind. Es kann sich um alles handeln, was Sie einem Klassennamen zuordnen möchten.
Orcun

6
Ich möchte nur hinzufügen, ich hatte ein Problem, weil ich Syntax wie verwendete {classname: '$index === selectedIndex'} und es nicht funktionierte. Als ich alles zusammengeschoben und == anstelle von === verwendet habe, hat es funktioniert. {classname: '$index==selectedIndex'}
Lucas

437

ng-class unterstützt einen Ausdruck, der entweder ausgewertet werden muss

  1. Eine Zeichenfolge von durch Leerzeichen getrennten Klassennamen oder
  2. Ein Array von Klassennamen oder
  3. Eine Zuordnung / ein Objekt von Klassennamen zu booleschen Werten.

Mit Form 3) können wir also einfach schreiben

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

Siehe auch Wie wende ich CSS-Stile in AngularJS bedingt an? für eine breitere Antwort.


Update : Angular 1.1.5 hat Unterstützung für einen ternären Operator hinzugefügt. Wenn Ihnen dieses Konstrukt also besser bekannt ist:

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

2
+1 für ternäre Operatoren (und ich brauche gerade einen), aber 1.1. * Ist eine 'instabile Version', bei der die API ohne vorherige Ankündigung geändert werden kann - zum Zeitpunkt der Eingabe. 1.0. * Ist stabil, daher wäre es für mich angenehmer, wenn ein Projekt nächste Woche für 6 Monate eingeführt würde.
Dave Everitt

1
ng-class="{'selected': $index==selectedIndex}"arbeitet für mich
Knuhol

160

Meine Lieblingsmethode ist die Verwendung des ternären Ausdrucks.

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

Hinweis: Wenn Sie eine ältere Version von Angular verwenden, sollten Sie diese stattdessen verwenden.

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

2
Dies hat mir geholfen, diesen Ausdruck zu schreiben : ng-class="property.name=='timestamp' ? 'property-timestamp' : 'property-'+{{$index}}". Konnte keinen anderen Weg herausfinden.
Dduft

Ich finde wirklich nicht heraus, warum mein boolescher Gültigkeitsbereich modalFlag nicht aktualisiert wird - ng-class = "{'closed': modalFlag, 'open' :! ModalFlag}" Ich versuche, je nach Gültigkeitsbereichsvariable / booleschem Wert entweder geschlossen oder offen hinzuzufügen - Wenn jemand helfen kann, wäre ich Ihnen sehr dankbar - danke.
landete

Dies wurde als 1.5-Version eingeführt. github.com/angular/angular.js/commit/…
Mubashir Koul

55

Ich werde noch etwas hinzufügen, da einige dieser Antworten veraltet zu sein scheinen. So mache ich das:

<class="ng-class:isSelected">

Wobei 'isSelected' eine Javascript-Variable ist, die innerhalb des Winkelreglers definiert ist.


Um Ihre Frage genauer zu beantworten, können Sie wie folgt eine Liste erstellen:

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


Siehe: http://jsfiddle.net/tTfWM/

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


Was ist der Unterschied zwischen class = "ng-class: item.isSelected" und ng-class = "item.isSelected"
zloctb

Neugierig auf die Verwendung von ng-class:classNamevs nur mit class="{{className}}"?
Roi

48

Hier ist eine viel einfachere Lösung:

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
Ich würde dringend empfehlen, Ihren Controller von CSS-Inhalten fernzuhalten. Das ist ein Weg, den du nicht beschreiten willst.
Leviathan

1
Klassennamen gehören in die Vorlage
Casey

5
Irgendwann versäumt es jsfiddle möglicherweise, seine Rechnungen zu bezahlen oder in eine andere Domain zu wechseln, oder die Verantwortlichen werden von einem Bus getötet (siehe auch Busfaktor). Darf ich Sie bitten, in Ihrer Antwort zu erklären, was diese Geige tut ? Dies ist auch beim Stapelüberlauf kanonisch.
Sebastian Mach

27

Ich hatte kürzlich ein ähnliches Problem und habe beschlossen, nur einen bedingten Filter zu erstellen:

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

Es wird ein einzelnes Argument benötigt, das entweder ein Array mit zwei Elementen oder eine Zeichenfolge ist, die in ein Array umgewandelt wird, an das eine leere Zeichenfolge als zweites Element angehängt wird:

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

1
Ich habe gerade einen yesNo () -Filter erstellt, der die Klassen 'yes' oder 'no' gemäß einem booleschen Wert 1 o 0 filter('yesNo', function() { return function(input) { // info('yesNo('+ input +')'); switch(input){ case '1': return ' yes '; break; default: return ' no '; break; } } });
zurückgibt

1
ng-class kann eine Zuordnung / ein Objekt von Klassennamen zu booleschen Werten verarbeiten, sodass Sie einfach Folgendes schreiben können: ng-class = "{yes: some_boolean_expression, no: some_other_boolean_expression}" ZB ng-class = "{yes: input , no :! input} "
Mark Rajcok

21

Wenn Sie über die binäre Auswertung hinausgehen und Ihr CSS von Ihrem Controller fernhalten möchten, können Sie einen einfachen Filter implementieren, der die Eingabe anhand eines Kartenobjekts auswertet:

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

Auf diese Weise können Sie Ihr Markup folgendermaßen schreiben:

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

Hallo @Joe, irgendwelche Ideen, wie man mit Nullwerten umgeht? Wenn ich in der Eingabe null übergebe,
ordnet

1
@ user1191559 - Sie könnten ein 'Standard'-Element in die Karte einfügen und diesen Wert dann zurückgeben, wenn' input 'null ist.
Joe Steele

17

Das habe ich kürzlich getan, als ich das tat:

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

Der isShowingWert ist ein Wert auf meinem Controller, der mit einem Klick auf eine Schaltfläche umgeschaltet wird. Die Teile zwischen den einzelnen Klammern sind Klassen, die ich in meiner CSS-Datei erstellt habe.

EDIT: Ich möchte auch hinzufügen, dass codeschool.com einen kostenlosen Kurs hat, der von Google auf AngularJS gesponsert wird und all diese und noch einige mehr Dinge behandelt. Sie müssen nichts bezahlen, melden Sie sich einfach für ein Konto an und legen Sie los! Viel Glück euch allen!


Könnten Sie hier eine Geige oder mehr Code bereitstellen? Befindet sich dann isShowingein Array im Controller?
Kyle Pennell

Ich denke, ist ein Boolescher
Mirko

15

Der ternäre Operator wurde gerade in 1.1.5 zum Winkelparser hinzugefügt .

Der einfachste Weg, dies zu tun, ist jetzt:

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

Auch : class="otherClass ng-class:($index==selectedIndex)? 'selected' : '';".
Peter

11

Wir können eine Funktion zum Verwalten der Rückgabeklasse mit Bedingung erstellen

Geben Sie hier die Bildbeschreibung ein

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

Und dann

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

Sie können sich bei Beispiel auf die vollständige Codepage in der ng-Klasse beziehen


9

Ich bin neu bei Angular, habe aber Folgendes gefunden, um mein Problem zu lösen:

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

Dadurch wird eine Klasse basierend auf einer Variable bedingt angewendet. Es beginnt standardmäßig mit einem Icon-Download , der Verwendung von ng-class. Ich überprüfe den Status von showDetailsif true/falseund wende den Icon-Upload der Klasse an . Es funktioniert großartig.

Ich hoffe es hilft.


9

Das funktioniert wie ein Zauber;)

<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

Dies wird wahrscheinlich in Vergessenheit geraten, aber hier ist, wie ich die ternären Operatoren von 1.1.5 verwendet habe, um Klassen zu wechseln, je nachdem, ob eine Zeile in einer Tabelle die erste, mittlere oder letzte ist - außer wenn es nur eine Zeile in der Tabelle gibt:

<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

Dies ist in meiner Arbeit mehrere bedingte Richter:

<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

Hier ist eine weitere Option, die gut funktioniert, wenn die ng-Klasse nicht verwendet werden kann (z. B. beim Stylen von SVG):

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

(Ich denke, Sie müssen auf dem neuesten instabilen Angular sein, um ng-attr- verwenden zu können. Ich bin derzeit auf 1.1.4)


4

Nun, ich würde vorschlagen, dass Sie den Zustand in Ihrem Controller mit einer Funktion überprüfen, die true oder false zurückgibt .

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

und überprüfen Sie in Ihrem Controller den Zustand

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

4

teilweise

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

Regler

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

3

Wenn Sie Angular Pre v1.1.5 (dh keinen ternären Operator) verwenden und dennoch eine äquivalente Methode zum Festlegen eines Werts unter beiden Bedingungen wünschen, können Sie Folgendes tun:

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

3

Wenn Sie eine gemeinsame Klasse haben, die auf viele Elemente angewendet wird, können Sie eine benutzerdefinierte Direktive erstellen, die diese Klasse wie ng-show / ng-hide hinzufügt.

Diese Anweisung fügt der Schaltfläche die Klasse 'active' hinzu, wenn darauf geklickt wird

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

Mehr Info



3

Überprüfen Sie dies .

Die berüchtigte AngularJS if|elseAussage !!!
Als ich anfing, Angularjs zu verwenden, war ich etwas überrascht, dass ich keine if / else-Anweisung finden konnte.

Ich habe an einem Projekt gearbeitet und festgestellt, dass bei Verwendung der if / else-Anweisung die Bedingung beim Laden angezeigt wird. Sie können ng-cloak verwenden, um dies zu beheben.

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

Danke amadou


0

Sie können dieses npm-Paket verwenden. Es behandelt alles und verfügt über Optionen für statische und bedingte Klassen, die auf einer Variablen oder einer Funktion basieren.

// 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})} />
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.