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

1183

Допустим , у вас есть массив , который визуализируется в ulс liдля каждого элемента и свойства на контроллере называется selectedIndex. Как лучше всего добавить класс liс индексом selectedIndexв AngularJS?

В настоящее время я дублирую (вручную) liкод и добавляю класс к одному из liтегов, а также использую ng-showи, ng-hideчтобы показать только один liиндекс.

respectTheCode
источник
2
Ответы на этот вопрос показывают, что в шаблонах есть нечто большее, чем {{varname}}. Где я могу найти документацию о том, что еще есть в шаблонах, таких как троичный оператор, в нескольких различных формах? docs.angularjs.org/guide/templates , по-видимому, не объясняет, что предлагает шаблон в терминах условий и т. д., кроме {{varname.fieldname}}.
Христос Хейворд
это очень полезно для меня, надеюсь, это сработает для вас tech-blog.maddyzone.com/javascript/…
Ритурай Ратан

Ответы:

1384

Если вы не хотите помещать имена классов CSS в Controller, как я, вот старая уловка, которую я использую с дней до v1. Мы можем написать выражение, которое оценивает непосредственно выбранное имя класса , никаких пользовательских директив не требуется:

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

Обратите внимание на старый синтаксис с двоеточием.

Существует также новый лучший способ условного применения классов, например:

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

Angular теперь поддерживает выражения, которые возвращают объект. Каждое свойство (имя) этого объекта теперь рассматривается как имя класса и применяется в зависимости от его значения.

Однако эти пути функционально не равны. Вот пример:

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

Поэтому мы могли бы повторно использовать существующие классы CSS, в основном сопоставляя свойство модели с именем класса и в то же время не допуская CSS-классов в коде контроллера.

Орчун
источник
33
OP, это может быть худший способ выражения троичного оператора, который я когда-либо видел. Вы рассматривали ($index==selectedIndex) ? 'selected' : ''?
Мальволио
17
@Malvolio AFAIR, троичный оператор не работал с угловыми выражениями в v0.9.x. Это более или менее переключатель.
октября
36
ng-class (по состоянию на 19.01.2012) теперь поддерживает выражение, которое должно оценивать либо 1) строку имен классов, разделенных пробелами, либо 2) и массив имен классов, либо 3) карту / объект класса имена для логических значений. Итак, используя 3): ng-class = "{selected: $ index == selectedIndex}"
Марк Раджкок
2
Спасибо @Mark, кстати, теперь, когда я проверил, я могу сказать, что этот метод работает в v1. Это все еще полезно в некоторых случаях. Обратите внимание, что имена свойств объектов (ключи) не обязательно являются истинными или ложными, это может быть что угодно, что вы хотите отобразить на имя класса.
orcun
6
Я просто хочу добавить, что у меня возникла проблема, потому что я использовал синтаксис, {classname: '$index === selectedIndex'} и он не работал. Когда я собрал все вместе и использовал == вместо ===, это сработало. {classname: '$index==selectedIndex'}
Лукас
437

ng-класс поддерживает выражение, которое должно вычислять либо

  1. Строка имен классов, разделенных пробелами, или
  2. Массив имен классов, или
  3. Карта / объект имен классов для логических значений.

Итак, используя форму 3) мы можем просто написать

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

Смотрите также Как я могу условно применять стили CSS в AngularJS? для более широкого ответа.


Обновление : в Angular 1.1.5 добавлена ​​поддержка троичного оператора , поэтому, если эта конструкция вам более знакома:

ng-class="($index==selectedIndex) ? 'selected' : ''"
Марк Райкок
источник
2
+1 для троичных операторов (и мне нужен один прямо сейчас), но 1.1. * Является «нестабильной версией», где API может изменяться без уведомления - на момент ввода текста. Версия 1.0. * Стабильна, поэтому мне было бы удобнее, если бы проект был запущен на следующей неделе в течение 6 месяцев.
Дэйв Эверитт
1
ng-class="{'selected': $index==selectedIndex}"у меня работает
кнухол
160

Мой любимый метод - использование троичного выражения.

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

Примечание: если вы используете более старую версию Angular, вы должны использовать это вместо этого,

ng-class="condition && 'trueClass' || 'falseClass'"
skmvasu
источник
2
Это помогло мне писать это выражение: ng-class="property.name=='timestamp' ? 'property-timestamp' : 'property-'+{{$index}}". Не смог придумать другого пути.
Ддуфт
Я действительно не понимаю, почему мой логический модуль scald modalFlag не обновляется - ng-class = "{'closed': modalFlag, 'open':! ModalFlag}" Я пытаюсь добавить закрытый или открытый в зависимости от заданной переменной / логического значения - если кто-нибудь может помочь, я был бы очень благодарен - спасибо.
приземлился
Это было введено как 1.5 версия. github.com/angular/angular.js/commit/…
Мубашир Коул
55

Я добавлю к этому, потому что некоторые из этих ответов кажутся устаревшими. Вот как я это делаю:

<class="ng-class:isSelected">

Где 'isSelected' - это переменная javascript, определенная в контроллере угловых значений.


Чтобы более конкретно ответить на ваш вопрос, вот как вы можете создать список с этим:

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


Смотрите: http://jsfiddle.net/tTfWM/

Смотрите: http://docs.angularjs.org/api/ng.directive:ngClass

Stefano
источник
В чем разница между class = "ng-class: item.isSelected" и ng-class = "item.isSelected"
zloctb
Любопытно на использование ng-class:classNameпротив просто использования class="{{className}}"?
Рой
48

Вот гораздо более простое решение:

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
Я настоятельно рекомендую держать ваш контроллер подальше от CSS. Это путь, по которому ты не хочешь идти вниз.
Левиафан
1
Имена классов принадлежат шаблону
Кейси
5
В какой-то момент jsfiddle может пропустить оплату своих счетов, либо перейти в другой домен, либо ответственные люди будут убиты автобусом (см. Также Фактор шины). Могу я попросить вас объяснить, что делает эта скрипка, в вашем ответе? Это также канонично при переполнении стека.
Себастьян Мах
27

Недавно я столкнулся с подобной проблемой и решил просто создать условный фильтр:

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

Он принимает один аргумент, который является либо 2-элементным массивом, либо строкой, которая превращается в массив, к которому добавляется пустая строка в качестве второго элемента:

<li ng-repeat="item in products | filter:search | orderBy:orderProp |
  page:pageNum:pageLength" ng-class="'opened'|if:isOpen(item)">
  ...
</li>
Lèse Majesté
источник
1
я только что создал для примера фильтр yesNo (), возвращающий классы 'yes' или 'no' в соответствии с логическим значением 1 o 0:filter('yesNo', function() { return function(input) { // info('yesNo('+ input +')'); switch(input){ case '1': return ' yes '; break; default: return ' no '; break; } } });
svassr
1
ng-class может обрабатывать карту / объект с именами классов в логических значениях, поэтому вы можете просто написать следующее: ng-class = "{yes: some_boolean_expression, no: some_other_boolean_expression}" Например, ng-class = "{yes: input , нет:! input} "
Марк Райкок
21

Если вы хотите выйти за рамки двоичной оценки и не использовать свой CSS в контроллере, вы можете реализовать простой фильтр, который оценивает входные данные по отношению к объекту карты:

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

Это позволяет вам написать вашу разметку следующим образом:

<div ng-class="muppets.star|switch:{'Kermit':'green', 'Miss Piggy': 'pink', 'Animal': 'loud'}">
    ...
</div>
Джо Стил
источник
Привет @Joe, есть идеи, как обрабатывать нулевые значения? Если я
передам
1
@ user1191559 - вы можете добавить элемент «по умолчанию» на карту, а затем вернуть это значение, если «input» равен нулю.
Джо Стил
17

То, что я недавно сделал, делало это:

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

isShowingЗначение представляет собой значение , которое находится на моем контроллере , который получает переключаемый с щелчком кнопки и части между одинарными скобками классами я создал в моем файле CSS.

РЕДАКТИРОВАТЬ: Я также хотел бы добавить, что у Codechool.com есть бесплатный курс, который спонсируется Google на AngularJS, который охватывает все эти вещи, а затем некоторые. Вам не нужно ничего платить, просто зарегистрируйтесь и начинайте! Желаем удачи всем вам!

Pytth
источник
Не могли бы вы предоставить скрипку или больше кода здесь? Есть isShowingли массив в контроллере?
Кайл Пеннелл
Я думаю, это логическое значение
Мирко
15

Тернарный оператор был добавлен в угловой парсер в 1.1.5 .

Итак, самый простой способ сделать это сейчас:

ng:class="($index==selectedIndex)? 'selected' : ''"
lionroots
источник
Кроме того : class="otherClass ng-class:($index==selectedIndex)? 'selected' : '';".
Питер
11

Мы можем сделать функцию для управления возвращаемым классом с условием

введите описание изображения здесь

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

А потом

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

Вы можете обратиться к полной кодовой странице в ng-классе, если пример

Льюис Хай
источник
9

Я новичок в Angular, но нашел это, чтобы решить мою проблему:

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

Это будет условно применять класс, основанный на var. Он начинается с загрузки значков по умолчанию, с использованием ng-класса, я проверяю статус showDetailsif true/falseи применяю class icon-upload . Работает отлично.

Надеюсь, поможет.

Рави Рам
источник
9

Это работает как шарм;)

<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>
Aliti
источник
5

Это, вероятно, будет забыто, но вот как я использовал тернарные операторы 1.1.5 для переключения классов в зависимости от того, является ли строка в таблице первой, средней или последней - за исключением того, что в таблице есть только одна строка:

<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

Это в моей работе несколько условно судить:

<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>
H.jame
источник
4

Вот еще один вариант, который хорошо работает, когда нельзя использовать ng-класс (например, при стилизации SVG):

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

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

Эшли Дэвис
источник
4

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

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

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

$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
sheelpriy
источник
4

частичный

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

контроллер

  $scope.campaign_range = "all";
  $scope.change_range = function(range) { 
        if (range === "all")
        {
            $scope.campaign_range = "all"
        }
        else
        {  
            $scope.campaign_range = "thismonth"
        }
  };
Caner Çakmak
источник
3

Если вы используете angular pre v1.1.5 (т.е. без тернарного оператора) и вам все еще нужен эквивалентный способ установки значения в обоих условиях, вы можете сделать что-то вроде этого:

ng-class="{'class1':item.isReadOnly == false, 'class2':item.isReadOnly == true}"
Scotty.NET
источник
3

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

Эта директива добавит класс «активный» к кнопке, если она нажата

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

Больше информации

lars1595
источник
3

Просто добавив что-то, что сработало для меня сегодня, после долгих поисков ...

<div class="form-group" ng-class="{true: 'has-error'}[ctrl.submitted && myForm.myField.$error.required]">

Надеюсь, что это помогает в вашем успешном развитии.

знак равно

Синтаксис недокументированного выражения: отличная ссылка на сайт ... =)

Роберт Грин MBA
источник
Проверьте принятый ответ. Он делает то же самое и дает больше примеров.
респект TheCode
3

Проверьте это .

Печально известное if|elseзаявление AngularJS !!!
Когда я начал использовать Angularjs, я был немного удивлен, что не смог найти оператор if / else.

Поэтому я работал над проектом и заметил, что при использовании оператора if / else условие отображается при загрузке. Вы можете использовать нг-плащ, чтобы исправить это.

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

Спасибо амаду

Виктор Круз
источник
0

Вы можете использовать этот пакет npm. Он обрабатывает все и имеет опции для статических и условных классов на основе переменной или функции.

// 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})} />
Тушар Шарма
источник