Как условно применять стили CSS в AngularJS?

Q1. Предположим, я хочу изменить внешний вид каждого "элемента", который пользователь отмечает для удаления до нажатия основной кнопки "Удалить". (Эта немедленная визуальная обратная связь должна устранить необходимость в пресловутом диалоговом окне "вы уверены?".) Пользователь установит флажки, чтобы указать, какие элементы следует удалить. Если флажок снят, этот элемент должен вернуться к нормальному виду.

Какой лучший способ применить или удалить стили CSS?

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

Какой лучший способ применить стиль CSS, который выбирает пользователь/входы?

Ответ 1

Angular предоставляет ряд встроенных директив для управления стилем CSS условно/динамически:

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

Обычный "Angular способ" включает привязку свойства model/scope к элементу пользовательского интерфейса, который будет принимать пользовательский ввод/манипулирование (т.е. использовать ng-model), а затем привязать это свойство модели к одному из встроенных элементов, в упомянутых выше директивах.

Когда пользователь меняет пользовательский интерфейс, Angular будет автоматически обновлять связанные элементы на странице.


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

ng-class принимает выражение, которое должно оцениваться одним из следующих:

  • строка имен классов с разделителями пространства
  • массив имен классов
  • карта/объект имен классов для логических значений

Предполагая, что ваши элементы отображаются с использованием ng-repeat над некоторой моделью массива и что при установке флажка для элемента вы хотите применить класс 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-класса # 3 - map/object имен классов для булевых значений.


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

ng-style принимает выражение, которое должно оцениваться с помощью:

  • карта/объект имен стиля CSS для значений CSS

Для надуманного примера предположим, что пользователь может ввести имя цвета в texbox для цвета фона (выбор цвета jQuery будет намного приятнее):

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


Fiddle для обоих вышеперечисленных.

В скрипте также содержится пример ng-show и ng-hide. Если флажок установлен, в дополнение к цвету заднего фона, отображается некоторый текст. Если в текстовое поле вводится "красный", div становится скрытым.

Ответ 2

Я обнаружил проблемы при применении классов внутри элементов table, когда у меня был один класс, уже примененный ко всей таблице (например, цвет, примененный к нечетным строкам <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 класс для всей таблицы.

UPDATE

Если вы хотите применить класс к таблице, например, при посещении страницы или в других случаях, вы можете использовать эту структуру:

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

В принципе, нам нужно активировать ng-class - это класс для применения и утверждение true или false. True применяет класс, а false - нет. Итак, у нас есть две проверки маршрута страницы и OR между ними, поэтому, если мы находимся в /route_a ИЛИ, мы находимся в route_b, active.

Это работает только с логической функцией справа, которая возвращает true или false.

Итак, в первом примере ng-style обусловлен тремя операторами. Если все они ложны, стиль не применяется, но, следуя нашей логике, по крайней мере одно будет применено, поэтому логическое выражение будет проверять, какое сравнение переменных истинно и потому что непустой массив всегда истинен, что будет оставил массив как возвращаемый и только с одним истинным, учитывая, что мы используем ИЛИ для всего ответа, будет сохранен стиль.

Кстати, я забыл дать вам функцию 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

Ответ 3

Это хорошо работает, когда 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

Ответ 4

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

Ответ 5

Это решение сделало трюк для меня

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

Ответ 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>

Ответ 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';
    }
};

Ответ 8

Вы можете использовать трехмерное выражение.

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

Ответ 9

По сравнению с 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 ...
}

Ответ 10

Еще один (в будущем) способ условного применения стиля заключается в условном создании облачного стиля

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

</style>

Но теперь FireFox поддерживает только облачные стили.

Ответ 11

Ну, я бы предложил вам проверить условие в вашем контроллере с функцией, возвращающей true или false.

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

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

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

Ответ 12

Еще один вариант, который я недавно обнаружил, что некоторые люди могут найти полезными, потому что он позволяет вам изменить правило CSS внутри элемента стиля, что позволяет избежать необходимости повторного использования директивы angular, такой как ng-style, ng-class, ng-show, ng-hide, ng-animate и другие.

Этот параметр использует сервис с переменными сервиса, которые устанавливаются контроллером и просматриваются директивой-атрибутом, которую я называю "custom-style". Эта стратегия может использоваться по-разному, и я попытался дать некоторые общие рекомендации этому fiddle.

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

Ответ 13

Одна вещь для просмотра - если стиль CSS имеет тире - вы должны удалить их. Поэтому, если вы хотите установить background-color, правильный способ:

ng-style="{backgroundColor:myColor}"