Jak warunkowo zastosować style CSS w AngularJS?

309

Pytanie 1 Załóżmy, że chcę zmienić wygląd każdego „elementu” zaznaczonego przez użytkownika do usunięcia przed naciśnięciem głównego przycisku „usuń”. (Ta natychmiastowa wizualna informacja zwrotna powinna wyeliminować potrzebę przysłowiowego okna dialogowego „jesteś pewien?”). Użytkownik zaznaczy pola wyboru, aby wskazać, które elementy należy usunąć. Jeśli pole wyboru nie jest zaznaczone, element powinien wrócić do normalnego wyglądu.

Jaki jest najlepszy sposób na zastosowanie lub usunięcie stylizacji CSS?

Q2 Załóżmy, że chcę pozwolić każdemu użytkownikowi na personalizację sposobu prezentacji mojej witryny. Np. Wybierz z ustalonego zestawu rozmiarów czcionek, zezwól na zdefiniowane przez użytkownika kolory pierwszego planu i tła itp.

Jaki jest najlepszy sposób zastosowania stylu CSS, który wybiera / wprowadza użytkownik?

Mark Rajcok
źródło
przydatny artykuł tech-blog.maddyzone.com/javascript/…
Rituraj ratan

Odpowiedzi:

485

Angular zapewnia szereg wbudowanych dyrektyw do warunkowego / dynamicznego manipulowania stylem CSS:

  • ng-class - użyj, gdy zestaw stylów CSS jest statyczny / znany z góry
  • ng-style - użyj, gdy nie możesz zdefiniować klasy CSS, ponieważ wartości stylu mogą się zmieniać dynamicznie. Pomyśl o programowalnej kontroli wartości stylu.
  • ng-show i ng-hide - użyj, jeśli potrzebujesz tylko coś pokazać lub ukryć (modyfikuje CSS)
  • ng-if - nowy w wersji 1.1.5, użyj zamiast bardziej szczegółowego przełącznika ng, jeśli musisz sprawdzić tylko jeden warunek (modyfikuje DOM)
  • ng-switch - użyj zamiast używać kilku wzajemnie wykluczających się pokazów (modyfikuje DOM)
  • ng-disabled i ng-readonly - służą do ograniczenia zachowania elementów formularza
  • ng-animate - nowość w wersji 1.1.4, służy do dodawania przejść / animacji CSS3

Normalny „sposób kątowy” obejmuje powiązanie właściwości model / scope z elementem interfejsu użytkownika, który zaakceptuje dane wejściowe / manipulację użytkownika (tj. Użycie ng-model), a następnie powiązanie tej właściwości modelu z jedną z wbudowanych dyrektyw wspomnianych powyżej.

Gdy użytkownik zmieni interfejs użytkownika, Angular automatycznie zaktualizuje powiązane elementy na stronie.


Q1 brzmi jak dobry przypadek dla klasy ng - styl CSS można uchwycić w klasie.

ng-class akceptuje „wyrażenie”, które musi zostać ocenione według jednego z poniższych:

  1. ciąg nazw klas rozdzielanych spacjami
  2. tablica nazw klas
  3. mapa / obiekt nazw klas na wartości boolowskie

Zakładając, że twoje elementy są wyświetlane za pomocą ng-repeat na jakimś modelu macierzowym, a gdy pole wyboru dla elementu jest zaznaczone, chcesz zastosować pending-deleteklasę:

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

Powyżej użyliśmy typu wyrażenia ng-class # 3 - mapę / obiekt nazw klas do wartości boolowskich.


Q2 brzmi jak dobry argument na styl ng - styl CSS jest dynamiczny, więc nie możemy zdefiniować dla tego klasy.

ng-style akceptuje „wyrażenie”, które należy ocenić, aby:

  1. mapa / obiekt nazw stylów CSS na wartości CSS

Dla wymyślonego przykładu załóżmy, że użytkownik może wpisać nazwę koloru w polu tekstowym dla koloru tła (próbnik kolorów jQuery byłby znacznie ładniejszy):

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


Skrzypki dla obu powyższych.

Skrzypce zawiera również przykład ng-show i ng-hide . Jeśli pole wyboru jest zaznaczone, oprócz koloru tła zmieniającego kolor na różowy, pojawia się tekst. Jeśli w polu tekstowym pojawi się „czerwony”, div zostanie ukryty.

Mark Rajcok
źródło
Ta odpowiedź jest wspaniała! Czy byłbyś skłonny pokazać mi przez jsfiddle, jaka byłaby różnica, gdyby zdarzenie click zmieniało / dodawało klasę do obszaru, który nie był klikanym elementem? Powiedz div gdzie indziej na stronie.
tehaaron,
przydatny artykuł tech-blog.maddyzone.com/javascript/…
Rituraj ratan
Świetna odpowiedź. A tak przy okazji, czy próbowałeś kiedyś zastosować filtr kątowy do stylu ng?
Evi Song,
Sugeruję dodanie dodatkowej opcji związanej z drugim kwartałem, którą właśnie dodałem w mojej ostatniej odpowiedzi na to pytanie.
Gavin Palmer,
105

Znalazłem problemy przy stosowaniu klas w elementach tabeli , gdy miałem już jedną klasę zastosowaną do całej tabeli (na przykład kolor zastosowany do nieparzystych wierszy <myClass tbody tr:nth-child(even) td>). Wydaje się, że podczas inspekcji elementu z Narzędzi Projektowych , element.stylema styl przypisany. Więc zamiast używać ng-class, próbowałem użyć ng-style, aw tym przypadku nowy atrybut CSS pojawia się w środku element.style. Ten kod działa dla mnie świetnie:

<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 jest tym, co oceniam , iw każdym przypadku stosuję styl do każdego w <td>zależności od wartości myvar , który zastępuje obecny styl zastosowany przez klasę CSS dla całej tabeli.

AKTUALIZACJA

Jeśli chcesz zastosować klasę do tabeli, na przykład podczas odwiedzania strony lub w innych przypadkach, możesz użyć tej struktury:

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

Zasadniczo, aby aktywować klasę ng , musimy zastosować klasę oraz prawdziwe lub fałszywe oświadczenie. Prawda stosuje się do klasy, a fałsz nie. Mamy więc dwa sprawdzanie trasy strony i OR między nimi, więc jeśli jesteśmy w /route_a OR, jesteśmy w route_b, zastosowana zostanie klasa aktywna .

Działa to po prostu z funkcją logiczną po prawej stronie, która zwraca true lub false.

W pierwszym przykładzie styl ng jest uwarunkowany trzema instrukcjami. Jeśli wszystkie są fałszywe, nie zostanie zastosowany żaden styl, ale zgodnie z naszą logiką zostanie zastosowany co najmniej jeden, więc wyrażenie logiczne sprawdzi, które porównanie zmiennych jest prawdziwe, a ponieważ niepusta tablica jest zawsze prawdziwa, to pozostawił tablicę jako return i tylko jedna prawda, biorąc pod uwagę, że używamy OR dla całej odpowiedzi, pozostały styl zostanie zastosowany.

Nawiasem mówiąc, zapomniałem podać ci funkcję isActive ():

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

NOWA AKTUALIZACJA

Tutaj masz coś, co uważam za bardzo przydatne. Gdy musisz zastosować klasę w zależności od wartości zmiennej, na przykład ikonę w zależności od zawartości div, możesz użyć następującego kodu (bardzo przydatnego w ng-repeat):

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

Ikony z Font Awesome

Timbergus
źródło
co dziwna składnia && powinna oznaczać ORAZ, jak w każdym innym języku inspirowanym językiem c
Pizzaiola Gorgonzola
3
@PizzaiolaGorgonzola && oznacza AND i || oznacza OR. To sprytny hack wykorzystujący logikę zwarć prawie jak instrukcję case / switch ...
Stein G. Strindhaug
Dzięki mit. Nie zdawałem sobie sprawy z tego szczegółu.
Timbergus,
Nowa sekcja aktualizacji działała jak urok! +1 za to!
Matias
użyłem przykładu klasy ng, jak wspomniano w New Update, działało całkiem dobrze dla mnie. Całkiem elegancki
Acewin
34

Działa to 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)

Opublikowałem artykuł o pracy z AngularJS + SVG. Mówi o tym problemie i wielu innych. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS

Ashley Davis
źródło
Nie widzę żadnej wzmianki o ng-attr w dokumentach 1.1.4 - czy masz link?
Mark Rajcok
Niestety nie mam linku. Dowiedziałem się o tym na forach Angular, choć nie pamiętam dokładnej strony przepraszam.
Ashley Davis,
1
Najnowsze dokumenty (v1.2) opisują ng-attr-na stronie dyrektyw , sekcja powiązania atrybutów ngAttr .
Mark Rajcok
W wersji 1.2 jest to świetna odpowiedź. ng-classnie pozwala ci wykonywać logiki, ale ng-attr-classrobi. Oba mają swoje zastosowania, ale mogę się założyć, że wielu programistów będzie szukało ng-attr-class.
Hylianpuffball
Sprawiłem, że działało dobrze, gdy zawiodły inne przedstawione tutaj rozwiązania. Dziękuję Ci.
dps
13
span class="circle circle-{{selectcss(document.Extension)}}">

i kod

$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);
}
Nenad Jesic
źródło
Zawsze unikaj słowa iF
LastTribunal 27.07.15
Chcę zachęcić do unikania bezpośredniego używania atrybutu class. Spowoduje to zastąpienie zmian wprowadzonych przez inne wtyczki w tym elemencie.
SimonSimCity
10

To rozwiązanie załatwiło sprawę

<a ng-style="{true: {paddingLeft: '25px'}, false: {}}[deleteTriggered]">...</a>
iamtankist
źródło
8

Możesz użyć wyrażenia trójskładnikowego. Można to zrobić na dwa sposoby:

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

lub...

<div ng-style="{'color': (myVariable > 100) ? 'red' : 'blue' }"></div>
michal-michalak
źródło
1
Może znajdziesz to lepiej: <div ng-style = "{'color': (myVariable> 100)? 'Red': 'blue'}"> </div>
Dudi
Dudi, jeśli nie lepszy, równie użyteczny, więc dodałem go do odpowiedzi na „wyrażenie potrójne” @ maykel. Dziękuję wam obu!
jbobbins
7

Inna opcja, gdy potrzebujesz prostego stylu css o jednej lub dwóch właściwościach:

Widok:

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

Kontroler:

$scope.getTrColor = function (colorIndex) {
    switch(colorIndex){
        case 0: return 'red';
        case 1: return 'green';
        default: return 'yellow';
    }
};
Dudi
źródło
6

Zobacz następujący przykład

<!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>
Ranga Reddy
źródło
2

Od AngularJS v1.2.0rc, ng-classa nawet ng-attr-classnie działa z elementami SVG (działały wcześniej, nawet przy normalnym wiązaniu wewnątrz atrybutu klasy)

W szczególności żaden z tych obecnie nie działa:

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

Aby obejść ten problem, muszę go użyć

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

a następnie styl za pomocą

[otherAttr='active'] {
   ... styles ...
}
kumarharsh
źródło
1

Kolejnym (w przyszłości) sposobem warunkowego zastosowania stylu jest warunkowe tworzenie stylu o zasięgu

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

</style>

Ale obecnie tylko FireFox obsługuje style o zasięgu.

Pavel Voronin
źródło
1

Jest jeszcze jedna opcja, którą niedawno odkryłem, że niektórzy ludzie mogą uznać ją za przydatną, ponieważ pozwala ona zmienić regułę CSS w elemencie stylu - unikając w ten sposób potrzeby wielokrotnego stosowania dyrektywy kątowej, takiej jak ng-style, ng-class, ng-show, ng-hide, ng-animate i inne.

Ta opcja korzysta z usługi ze zmiennymi usługowymi, które są ustawiane przez kontroler i obserwowane przez dyrektywę atrybutów, którą nazywam „stylem niestandardowym”. Tę strategię można wykorzystać na wiele różnych sposobów i starałem się udzielić ogólnych wskazówek dotyczących tego skrzypka .

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);
        }
    };
});
Gavin Palmer
źródło
1

cóż, sugeruję sprawdzenie stanu w kontrolerze za pomocą funkcji zwracającej wartość true lub false .

<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);
}
Sheelpriy
źródło
0

Jedną rzeczą do obejrzenia jest - jeśli styl CSS ma myślniki - musisz je usunąć. Więc jeśli chcesz ustawić background-color, poprawny sposób to:

ng-style="{backgroundColor:myColor}" 
Neil Munro
źródło
5
Nie musisz. ng-style = "{'background-color': myColor}" działa doskonale.
gerasalus
0

Oto jak warunkowo zastosowałem szary styl tekstu na wyłączonym przycisku

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

Oto działający przykład:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

BraveNewMath
źródło