Wie wende ich CSS-Stile in AngularJS bedingt an?


309

Q1. Angenommen, ich möchte das Aussehen jedes "Elements" ändern, das ein Benutzer zum Löschen markiert, bevor die Hauptschaltfläche "Löschen" gedrückt wird. (Durch diese sofortige visuelle Rückmeldung sollte das sprichwörtliche Dialogfeld "Sind Sie sicher?" Nicht mehr erforderlich sein.) Der Benutzer aktiviert die Kontrollkästchen, um anzugeben, welche Elemente gelöscht werden sollen. Wenn ein Kontrollkästchen deaktiviert ist, sollte dieses Element wieder normal aussehen.

Was ist der beste Weg, um das CSS-Styling anzuwenden oder zu entfernen?

Q2. Angenommen, ich möchte jedem Benutzer erlauben, die Darstellung meiner Website zu personalisieren. Wählen Sie beispielsweise aus einem festen Satz von Schriftgrößen aus, lassen Sie benutzerdefinierte Vordergrund- und Hintergrundfarben zu usw.

Wie kann das vom Benutzer ausgewählte / eingegebene CSS-Styling am besten angewendet werden?


Antworten:


485

Angular bietet eine Reihe integrierter Anweisungen zum bedingten / dynamischen Bearbeiten des CSS-Stils:

  • ng-class - Wird verwendet, wenn der Satz von CSS-Stilen im Voraus statisch / bekannt ist
  • ng-style - Wird verwendet, wenn Sie keine CSS-Klasse definieren können, da sich die Stilwerte möglicherweise dynamisch ändern. Denken Sie an eine programmierbare Steuerung der Stilwerte.
  • ng-show und ng-hide - Verwenden Sie diese Option , wenn Sie nur etwas ein- oder ausblenden müssen (ändert CSS).
  • ng-if - neu in Version 1.1.5, verwenden Sie anstelle des ausführlicheren ng-Schalters, wenn Sie nur nach einer einzelnen Bedingung suchen müssen (ändert DOM)
  • ng-switch - Verwenden Sie anstelle mehrerer sich gegenseitig ausschließender ng-Shows (ändert DOM)
  • ng-disabled und ng-readonly - wird verwendet, um das Verhalten von Formularelementen einzuschränken
  • ng-animate - neu in Version 1.1.4, zum Hinzufügen von CSS3-Übergängen / -Animationen

Der normale "Winkelweg" besteht darin, eine Modell- / Bereichseigenschaft an ein UI-Element zu binden, das Benutzereingaben / -manipulationen akzeptiert (dh ng-model verwendet), und diese Modelleigenschaft dann einer der oben genannten integrierten Anweisungen zuzuordnen.

Wenn der Benutzer die Benutzeroberfläche ändert, aktualisiert Angular automatisch die zugehörigen Elemente auf der Seite.


Q1 klingt nach einem guten Fall für die ng-Klasse - das CSS-Styling kann in einer Klasse erfasst werden.

ng-class akzeptiert einen "Ausdruck", der einen der folgenden Werte ergeben muss:

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

Angenommen, Ihre Elemente werden mit ng-repeat über ein Array-Modell angezeigt, und wenn das Kontrollkästchen für ein Element aktiviert ist, möchten Sie die pending-deleteKlasse anwenden :

<div ng-repeat="item in items" ng-class="{'pending-delete': item.checked}">
   ... HTML to display the item ...
   <input type="checkbox" ng-model="item.checked">
</div>

Oben haben wir den Ausdruckstyp # 3 der ng-Klasse verwendet - eine Zuordnung / ein Objekt von Klassennamen zu booleschen Werten.


Q2 klingt nach einem guten Fall für ng-style - das CSS-Styling ist dynamisch, daher können wir hierfür keine Klasse definieren.

ng-style akzeptiert einen "Ausdruck", der ausgewertet werden muss für:

  1. eine Zuordnung / ein Objekt von CSS-Stilnamen zu CSS-Werten

Angenommen, der Benutzer kann einen Farbnamen in eine Texbox für die Hintergrundfarbe eingeben (ein jQuery-Farbwähler wäre viel besser):

<div class="main-body" ng-style="{color: myColor}">
   ...
   <input type="text" ng-model="myColor" placeholder="enter a color name">


Geige für beide oben genannten.

Die Geige enthält auch ein Beispiel für ng-show und ng-hide . Wenn ein Kontrollkästchen aktiviert ist, wird zusätzlich zu der rosa gefärbten Hintergrundfarbe Text angezeigt. Wenn 'rot' in das Textfeld eingegeben wird, wird ein div ausgeblendet.


Diese Antwort ist großartig! Wären Sie bereit, mir über jsfiddle zu zeigen, was der Unterschied wäre, wenn das Klickereignis eine Klasse in einem Bereich ändern / hinzufügen würde, der nicht das angeklickte Element ist? Sagen Sie eine Div an anderer Stelle auf der Seite.
Tehaaron


Großartige Antwort. Übrigens, haben Sie jemals versucht, einen Winkelfilter auf den ng-Stil anzuwenden?
Evi Song

Ich schlage vor, eine zusätzliche Option für das zweite Quartal hinzuzufügen, die ich gerade in meiner letzten Antwort auf diese Frage hinzugefügt habe.
Gavin Palmer

105

Ich habe Probleme beim Anwenden von Klassen in Tabellenelementen festgestellt, als ich bereits eine Klasse auf die gesamte Tabelle angewendet hatte (z. B. eine Farbe, die auf die ungeraden Zeilen angewendet wurde <myClass tbody tr:nth-child(even) td>). Wenn Sie das Element mit den Entwicklertools untersuchen , wird dem anscheinend element.stylekein Stil zugewiesen. Anstatt zu verwenden ng-class, habe ich versucht, zu verwenden ng-style, und in diesem Fall wird das neue CSS-Attribut im Inneren angezeigt element.style. Dieser Code funktioniert gut für mich:

<tr ng-repeat="element in collection">

    [...amazing code...]

    <td ng-style="myvar === 0 && {'background-color': 'red'} ||
                  myvar === 1 && {'background-color': 'green'} ||
                  myvar === 2 && {'background-color': 'yellow'}">{{ myvar }}</td>

    [...more amazing code...]

</tr>

Myvar ist das, was ich evaluiere, und in jedem Fall wende ich <td>je nach myvar- Wert einen Stil auf jeden an , der den aktuellen Stil überschreibt, den die CSS-Klasse für die gesamte Tabelle anwendet.

AKTUALISIEREN

Wenn Sie beispielsweise beim Besuch einer Seite oder in anderen Fällen eine Klasse auf die Tabelle anwenden möchten, können Sie folgende Struktur verwenden:

<li ng-class="{ active: isActive('/route_a') || isActive('/route_b')}">

Grundsätzlich benötigen wir zum Aktivieren einer ng-Klasse die anzuwendende Klasse und eine wahre oder falsche Aussage. True wendet die Klasse an und false nicht. Hier haben wir also zwei Überprüfungen der Route der Seite und ein ODER zwischen ihnen. Wenn wir uns also im /route_a ODER befinden route_b, wird die aktive Klasse angewendet.

Dies funktioniert nur mit einer Logikfunktion auf der rechten Seite, die true oder false zurückgibt.

Im ersten Beispiel wird ng-style also durch drei Anweisungen bedingt. Wenn alle falsch sind, wird kein Stil angewendet, aber gemäß unserer Logik wird mindestens einer angewendet. Der logische Ausdruck prüft also, welcher Variablenvergleich wahr ist, und da ein nicht leeres Array immer wahr ist, wird dies der Fall sein hat ein Array als return hinterlassen und mit nur einem true, wenn man bedenkt, dass wir OR für die gesamte Antwort verwenden, wird der verbleibende Stil angewendet.

Übrigens habe ich vergessen, Ihnen die Funktion isActive () zu geben:

$rootScope.isActive = function(viewLocation) {
    return viewLocation === $location.path();
};

NEUES UPDATE

Hier haben Sie etwas, das ich wirklich nützlich finde. Wenn Sie eine Klasse abhängig vom Wert einer Variablen anwenden müssen, z. B. ein Symbol, das vom Inhalt der Variablen abhängt, divkönnen Sie den folgenden Code verwenden (sehr nützlich in ng-repeat):

<i class="fa" ng-class="{ 'fa-github'   : type === 0,
                          'fa-linkedin' : type === 1,
                          'fa-skype'    : type === 2,
                          'fa-google'   : type === 3 }"></i>

Icons von Font Awesome


Was für eine seltsame Syntax, && sollte UND bedeuten, wie in jeder anderen von C inspirierten Sprache
Pizzaiola Gorgonzola

3
@PizzaiolaGorgonzola && bedeutet UND und || bedeutet ODER. Es ist ein kluger Hack, der die Kurzschlusslogik fast als Fall- / Schalteranweisung verwendet ...
Stein G. Strindhaug

Danke mit. Ich habe dieses Detail nicht bemerkt.
Timbergus

Der neue Update-Bereich hat wie ein Zauber funktioniert! +1 dafür!
Matias

habe das Beispiel der ng-Klasse verwendet, wie in New Update erwähnt, hat für mich ziemlich gut funktioniert. Ziemlich schlank
Acewin

34

Dies funktioniert gut, 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)

Ich habe einen Artikel über die Arbeit mit AngularJS + SVG veröffentlicht. Es spricht über dieses Thema und zahlreiche andere. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS


In den 1.1.4-Dokumenten wird ng-attr nicht erwähnt. Haben Sie einen Link?
Mark Rajcok

Entschuldigung, ich habe keinen Link. Ich habe es herausgefunden, indem ich den Angular-Foren gefolgt bin, obwohl ich mich leider nicht an die genaue Seite erinnern kann.
Ashley Davis

1
Die neuesten Dokumente (v1.2) beschreiben ng-attr-auf der Direktivenseite den Abschnitt ngAttr-Attributbindungen .
Mark Rajcok

Mit 1.2 wird dies eine großartige Antwort. ng-classlässt Sie keine Logik ausführen, ng-attr-classtut es aber . Sie haben beide ihre Verwendung, aber ich kann wetten, dass viele Entwickler danach suchen werden ng-attr-class.
Hylianpuffball

Ich habe dies gut funktionieren lassen, als andere hier bereitgestellte Lösungen fehlschlugen. Vielen Dank.
dps

13
span class="circle circle-{{selectcss(document.Extension)}}">

und Code

$scope.selectcss = function (data) {
    if (data == '.pdf')
        return 'circle circle-pdf';
    else
        return 'circle circle-small';
};

CSS

.circle-pdf {
    width: 24px;
    height: 24px;
    font-size: 16px;
    font-weight: 700;
    padding-top: 3px;
    -webkit-border-radius: 12px;
    -moz-border-radius: 12px;
    border-radius: 12px;
    background-image: url(images/pdf_icon32.png);
}

Vermeiden Sie immer das iF-Wort
LastTribunal

Ich möchte ermutigen, die direkte Verwendung des Klassenattributs zu vermeiden. Dadurch werden Änderungen überschrieben, die von anderen Plugins für dieses Element vorgenommen wurden.
SimonSimCity

10

Diese Lösung hat den Trick für mich getan

<a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>

8

Sie können einen ternären Ausdruck verwenden. Es gibt zwei Möglichkeiten, dies zu tun:

<div ng-style="myVariable > 100 ? {'color': 'red'} : {'color': 'blue'}"></div>

oder...

<div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>

1
Vielleicht findest du es besser: <div ng-style = "{'color': (myVariable> 100)? 'Red': 'blue'}"> </ div>
Dudi

Dudi, wenn nicht besser, genauso nützlich, also habe ich es zu @ maykels Antwort "ternärer Ausdruck" hinzugefügt. Danke euch beiden!
Jbobbins

7

Eine weitere Option, wenn Sie einen einfachen CSS-Stil mit einer oder zwei Eigenschaften benötigen:

Aussicht:

<tr ng-repeat="element in collection">
    [...amazing code...] 
    <td ng-style="{'background-color': getTrColor(element.myvar)}">
        {{ element.myvar }}
    </td>
    [...more amazing code...]
</tr>

Regler:

$scope.getTrColor = function (colorIndex) {
    switch(colorIndex){
        case 0: return 'red';
        case 1: return 'green';
        default: return 'yellow';
    }
};

6

Siehe folgendes Beispiel

<!DOCTYPE html>
    <html ng-app>
    <head>
    <title>Demo Changing CSS Classes Conditionally with Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
    <script src="res/js/controllers.js"></script>

    <style>

    .checkboxList {
        border:1px solid #000;
        background-color:#fff;
        color:#000;
        width:300px;
        height: 100px;
        overflow-y: scroll;
    }

    .uncheckedClass {
       background-color:#eeeeee;
       color:black;
    }
    .checkedClass {
        background-color:#3ab44a;
        color:white;
    }
    </style>

    </head>
    <body ng-controller="TeamListCtrl">
    <b>Teams</b>
    <div id="teamCheckboxList" class="checkboxList">

    <div class="uncheckedClass" ng-repeat="team in teams" ng-class="{'checkedClass': team.isChecked, 'uncheckedClass': !team.isChecked}">

    <label>
    <input type="checkbox" ng-model="team.isChecked" />
    <span>{{team.name}}</span>
    </label>
    </div>
    </div>
    </body>
    </html>

2

Ab AngularJS v1.2.0rc ng-classund sogar ng-attr-classmit SVG-Elementen fehlgeschlagen (Sie haben früher funktioniert, auch mit normaler Bindung innerhalb des Klassenattributs).

Insbesondere funktioniert keine dieser Funktionen jetzt:

ng-class="current==this_element?'active':' ' "
ng-attr-class="{{current==this_element?'active':' '}}"
class="class1 class2 .... {{current==this_element?'active':''}}"

Als Workaround muss ich verwenden

ng-attr-otherAttr="{{current==this_element?'active':''}}"

und dann mit stylen

[otherAttr='active'] {
   ... styles ...
}

1

Eine weitere Möglichkeit (in Zukunft), den Stil bedingt anzuwenden, besteht darin, den Stil mit Gültigkeitsbereich bedingt zu erstellen

<style scoped type="text/css" ng-if="...">

</style>

Heutzutage unterstützt jedoch nur FireFox Stile mit Gültigkeitsbereich.


1

Es gibt noch eine weitere Option, die ich kürzlich entdeckt habe und die einige Leute möglicherweise nützlich finden, weil sie es Ihnen ermöglicht, eine CSS-Regel innerhalb eines Stilelements zu ändern, wodurch die Notwendigkeit einer wiederholten Verwendung einer Winkelanweisung wie ng-style, ng-class, vermieden wird. ng-show, ng-hide, ng-animate und andere.

Diese Option verwendet einen Dienst mit Dienstvariablen, die von einem Controller festgelegt und von einer Attributanweisung überwacht werden, die ich als "benutzerdefinierten Stil" bezeichne. Diese Strategie kann auf viele verschiedene Arten angewendet werden, und ich habe versucht, mit dieser Geige eine allgemeine Anleitung zu geben .

var app = angular.module('myApp', ['ui.bootstrap']);
app.service('MainService', function(){
    var vm = this;
});
app.controller('MainCtrl', function(MainService){
    var vm = this;
    vm.ms = MainService;
});
app.directive('customStyle', function(MainService){
    return {
        restrict : 'A',
        link : function(scope, element, attr){
            var style = angular.element('<style></style>');
            element.append(style);
            scope.$watch(function(){ return MainService.theme; },
                function(){
                    var css = '';
                    angular.forEach(MainService.theme, function(selector, key){
                        angular.forEach(MainService.theme[key], function(val, k){
                            css += key + ' { '+k+' : '+val+'} ';
                        });                        
                    });
                    style.html(css);
                }, true);
        }
    };
});

1

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

0

Eine Sache, die Sie beachten sollten, ist, dass Sie sie entfernen müssen, wenn der CSS-Stil Bindestriche enthält. Wenn Sie also einstellen möchten, background-colorist der richtige Weg:

ng-style="{backgroundColor:myColor}" 

5
Nein, das musst du nicht. ng-style = "{'Hintergrundfarbe': myColor}" funktioniert einwandfrei.
Gerasalus

0

Hier ist, wie ich den grauen Textstil bedingt auf eine deaktivierte Schaltfläche angewendet habe

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  styleUrls: [ './app.component.css' ],
  template: `
  <button 
    (click)='buttonClick1()' 
    [disabled] = "btnDisabled"
    [ngStyle]="{'color': (btnDisabled)? 'gray': 'black'}">
    {{btnText}}
  </button>`
})
export class AppComponent  {
  name = 'Angular';
  btnText = 'Click me';
  btnDisabled = false;
  buttonClick1() {
    this.btnDisabled = true;
    this.btnText = 'you clicked me';
    setTimeout(() => {
      this.btnText = 'click me again';
      this.btnDisabled = false
      }, 5000);
  }
}

Hier ist ein funktionierendes Beispiel:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

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.