Як я можу умовно застосувати стилі CSS в AngularJS?


309

Q1. Припустимо, я хочу змінити вигляд кожного "елемента", який користувач відмічає для видалення, перш ніж натиснути головну кнопку "видалити". (Цей негайний візуальний зворотний зв'язок повинен усунути необхідність у поговорному діалоговому вікні "Ви впевнені?". Користувач встановить прапорці, щоб вказати, які елементи слід видалити. Якщо прапорець не встановлений, цей елемент повинен повернутися до його нормального вигляду.

Який найкращий спосіб застосувати або видалити CSS-стиль?

Q2. Припустимо, я хочу дозволити кожному користувачеві персоналізувати, як представлений мій сайт. Наприклад, виберіть із фіксованого набору розмірів шрифту, дозвольте визначені користувачем кольори переднього плану та фону тощо.

Який найкращий спосіб застосувати CSS-стиль, який користувач вибирає / вводить?


Відповіді:


485

Angular пропонує ряд вбудованих директив для маніпулювання CSS-стилем умовно / динамічно:

  • ng-class - використання, коли набір стилів CSS статичний / відомий достроково
  • ng-style - використовуйте, коли ви не можете визначити клас CSS, оскільки значення стилів можуть динамічно змінюватися. Подумайте програмоване управління значеннями стилю.
  • ng-show та ng-hid - використовуйте, якщо вам потрібно лише щось показати або приховати (змінює CSS)
  • ng-if - нове у версії 1.1.5, використовуйте замість більш багатослівного ng-перемикача, якщо вам потрібно перевірити лише одну умову (модифікує DOM)
  • ng-switch - використання замість декількох взаємовиключних ng-шоу (модифікує DOM)
  • ng-disabled та ng-readonly - використовувати для обмеження поведінки елементів форми
  • ng-animate - новий у версії 1.1.4, використовуйте для додавання CSS3 переходів / анімацій

Звичайний "кутовий спосіб" передбачає прив'язку властивості моделі / області до елемента інтерфейсу, який буде приймати введення / маніпуляцію користувача (тобто використовувати ng-модель), а потім асоціювати цю властивість моделі з однією з вбудованих директив, згаданих вище.

Коли користувач змінить інтерфейс користувача, Angular автоматично оновить пов'язані елементи на сторінці.


Q1 звучить як хороший випадок для ng-класу - стилі CSS можуть бути захоплені у класі.

ng-class приймає "вираз", який повинен оцінювати одне з наступних:

  1. рядок імен класів з обмеженим пробілом
  2. масив назв класів
  3. карта / об'єкт імен класів до булевих значень

Якщо припустити, що ваші елементи відображаються за допомогою ng-повтору над деякою моделлю масиву, і що, коли прапорець для цього пункту встановлено, ви хочете застосувати pending-deleteклас:

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

Вище ми використовували вираз ng-class type # 3 - карта / об’єкт імен класів для булевих значень.


Q2 звучить як хороший випадок для ng-стилю - CSS-стиль є динамічним, тому ми не можемо визначити клас для цього.

ng-style приймає "вираз", який повинен оцінювати:

  1. карта / об’єкт імен стилів CSS до значень CSS

Для надуманого прикладу, припустимо, що користувач може ввести ім'я кольору в текстове поле для кольору тла (вибір кольору jQuery був би набагато приємнішим):

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


Скрипка для обох вищезазначених.

Загадка також містить приклад ng-show та ng-hid . Якщо прапорець встановлений, окрім того, що фоновий колір стає рожевим, відображається деякий текст. Якщо в текстовому полі введено 'червоний', діва стає прихованим.


Ця відповідь приголомшлива! Чи хочете ви показати мені через jsfiddle, яка різниця була б, якщо подія клацання змінювалась / додавала клас у зоні, на якій не було клацання елемента? Скажіть діву в іншому місці на сторінці.
tehaaron


Великий привид. Btw, ви коли-небудь намагалися застосувати кутовий фільтр до ng-стилю?
Пісня Evi

Я пропоную додати додатковий варіант, що стосується Q2, який я щойно додав у своїй нещодавній відповіді на це питання.
Гевін Палмер

105

Я виявив проблеми при застосуванні класів всередині таблицю елементів , коли я був один клас вже застосовується до всієї таблиці (наприклад, колір застосовується до непарних рядках <myClass tbody tr:nth-child(even) td>). Здається, що при огляді елемента за допомогою Інструментів для розробників , element.styleстиль не призначений. Тому замість використання ng-classя намагався використовувати ng-style, і в цьому випадку новий атрибут CSS все-таки з’являється всередині element.style. Цей код для мене чудово працює:

<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 - це те, що я оцінюю , і в кожному випадку я застосовую стиль до кожного, <td>залежно від значення myvar , який замінює поточний стиль, застосований класом CSS для всієї таблиці.

ОНОВЛЕННЯ

Якщо ви хочете застосувати клас до таблиці, наприклад, під час відвідування сторінки або в інших випадках, ви можете використовувати цю структуру:

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

В основному, нам потрібно активувати ng-клас - клас, який слід застосувати, і правдиве або хибне твердження. True застосовує клас, а false - ні. Отже, у нас є дві перевірки маршруту сторінки та АБО між ними, тож якщо ми знаходимось в /route_a АБО, ми знаходимося route_b, буде застосовано активний клас.

Це працює просто з логічною функцією праворуч, яка повертає значення true та false.

Так у першому прикладі стиль ng зумовлений трьома твердженнями. Якщо всі вони помилкові, не застосовується жоден стиль, але слідуючи нашій логіці, принаймні один буде застосований, тож, логічний вираз перевірить, яке порівняння змінної є істинним, і тому, що не порожній масив завжди істинний, це буде залишив масив як повернення і лише з одним істинним, враховуючи, що ми використовуємо АБО для всієї відповіді, залишився стиль.

До речі, я забув надати вам функцію isActive ():

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

НОВА ОНОВЛЕННЯ

Тут у вас є щось, що я вважаю дійсно корисним. Коли вам потрібно застосувати клас залежно від значення змінної, наприклад, піктограми залежно від вмісту div, ви можете використовувати наступний код (дуже корисний у ng-repeat):

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

Ікони з шрифту Awesome


що дивний синтаксис, && має означати AND, як і в будь-якій іншій мові, натхненній c
Pizzaiola Gorgonzola

3
@PizzaiolaGorgonzola && означає І, і || означає АБО. Це розумний злом, що використовує логіку короткого замикання майже як випадок випадку / вимикача ...
Stein G. Strindhaug

Спасибі міт. Я не розумів цієї деталі.
Тимберг

Новий розділ оновлень спрацював як шарм! +1 за це!
Matias

використовував приклад ng-класу, як згадується в Новому оновлення, працював для мене досить добре. Досить гладкий
Асевін

34

Це добре працює, коли ng-клас неможливо використовувати (наприклад, для стилювання SVG):

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

(Я думаю, що вам потрібно мати останній нестабільний Angular, щоб використовувати ng-attr-, зараз я перебуваю на 1.1.4)

Я опублікував статтю про роботу з AngularJS + SVG. У ньому йдеться про це питання та численні інші. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS


Я не бачу жодної згадки про ng-attr в документах 1.1.4 - у вас є посилання?
Марк Райкок

На жаль, немає посилання. Я дізнався про це, переглянувши форуми Angular, хоча не можу пригадати точну сторінку.
Ешлі Девіс

1
Останні документи (v1.2) описують ng-attr-на сторінці директив , розділ прив’язки атрибутів ngAttr .
Марк Райкок

З 1.2 це стає чудовою відповіддю. ng-classне дозволяє виконувати логіку, але ng-attr-classробить. Вони обидва мають своє використання, але я можу обміняти, що багато розробників будуть шукати ng-attr-class.
Hylianpuffball

Я змусив це добре працювати, коли інші рішення, запропоновані тут, не вдається. Дякую.
дпс

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

і код

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

Завжди уникайте слова iF
LastTribunal

Я хочу заохотити уникати прямого використання класу-атрибута. Це замінить зміни, внесені іншими плагінами цього елемента.
SimonSimCity

10

Це рішення зробило для мене трюк

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

8

Можна використовувати потрійний вираз. Є два способи зробити це:

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

або ...

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

1
Може бути, вам стане краще: <div ng-style = "{'color': (myVariable> 100)? 'Red': 'blue'}"> </div>
Dudi

Дуді, якщо не краще, так само корисно, тож я додав його до відповіді на "майстерне вираз" @ Maykel. Дякую обом!
jbobbins

7

Ще один варіант, коли вам потрібен простий стиль css з однієї або двох властивостей:

Вид:

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

Контролер:

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

6

Дивіться наступний приклад

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

Станом на AngularJS v1.2.0rc ng-classі навітьng-attr-class не вдається з елементами SVG (Вони працювали раніше, навіть із нормальним зв'язуванням всередині атрибута класу)

Зокрема, жоден з цих питань зараз не працює:

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

Як вирішення, я повинен використовувати

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

а потім стиль використання

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

1

Ще один (у майбутньому) спосіб умовно застосувати стиль - це умовно створити масштабний стиль

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

</style>

Але на сьогоднішній день тільки FireFox підтримує стилі масштабування.


1

Є ще один варіант, який я нещодавно виявив, що деякі люди можуть виявитись корисними, оскільки це дозволяє змінити правило CSS в рамках елемента стилю - таким чином уникнути необхідності повторного використання кутової директиви, наприклад, ng-style, ng-class, ng-show, ng-hid, ng-animate та інші.

Цей параметр використовує послугу зі службовими змінними, які встановлюються контролером і переглядаються атрибутом-директивою, яку я називаю "користувальницький стиль". Ця стратегія могла використовуватися різними способами, і я спробував дати деякі загальні вказівки з цим загадком .

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

добре, я б запропонував вам перевірити стан у вашому контролері з функцією, що повертає значення true чи false .

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

і у своєму контролері перевірити стан

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

0

Одне, на що слід звернути увагу, - якщо у стилі CSS є тире, ви повинні їх видалити. Отже, якщо ви хочете встановити background-color, правильний спосіб:

ng-style="{backgroundColor:myColor}" 

5
Ні, не потрібно. ng-style = "{'background-color': myColor}" працює чудово.
gerasalus

0

Ось як я умовно застосував сірий стиль тексту до відключеної кнопки

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

Ось робочий приклад:
https://stackblitz.com/edit/example-conditional-disable-button?file=src%2Fapp%2Fapp.component.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.