Как лучше всего условно применить класс?
У меня есть массив, который отображается в элементе <ul>
, где для каждого элемента создается <li>
. В контроллере имеется свойство selectedIndex
. Какой лучший способ добавить класс к <li>
с индексом selectedIndex
в AngularJS?
В настоящее время я дублирую (вручную) код <li>
и добавляю класс к одному из тегов <li>
, используя ng-show
и ng-hide
, чтобы отображать только один <li>
для каждого индекса.
5 ответ(ов)
Если вы не хотите помещать имена CSS-классов в контроллер, как это делаю я, вот старый прием, которым я пользуюсь с до-версии 1. Мы можем написать выражение, которое будет напрямую оцениваться в имя класса selected, без необходимости в создании пользовательских директив:
ng:class="{true:'selected', false:''}[$index==selectedIndex]"
Обратите внимание на старый синтаксис с двоеточием.
Существуют также новые и более эффективные способы условного применения классов, такие как:
ng-class="{selected: $index==selectedIndex}"
Теперь Angular поддерживает выражения, которые возвращают объект. Каждое свойство (имя) этого объекта считается именем класса и применяется в зависимости от его значения.
Тем не менее, эти подходы не равнозначны с функциональной точки зрения. Вот пример:
ng-class="{admin:'enabled', moderator:'disabled', '':'hidden'}[user.role]"
Таким образом, мы можем повторно использовать существующие CSS-классы, в основном сопоставляя свойство модели с именем класса, и одновременно исключить CSS-классы из кода контроллера.
Мой любимый способ — использование тернарного оператора.
ng-class="condition ? 'trueClass' : 'falseClass'"
Примечание: Если вы используете более старую версию Angular, вам следует использовать следующий подход:
ng-class="condition && 'trueClass' || 'falseClass'"
Я добавлю сюда свою версию, потому что некоторые из этих ответов могут быть устаревшими. Вот как я это делаю:
<li class="ng-class:isSelected">
Где isSelected
— это переменная JavaScript, определенная в контроллере Angular с областью видимости.
Чтобы более конкретно ответить на ваш вопрос, вот как можно сгенерировать список:
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": ""}
];
}
Вы можете протестировать это здесь: jsfiddle.net/tTfWM
Смотрите также: документация AngularJS по ngClass
Вот гораздо более простое решение:
function MyControl($scope){
$scope.values = ["a", "b", "c", "d", "e", "f"];
$scope.selectedIndex = -1;
$scope.toggleSelect = function(ind){
$scope.selectedIndex = (ind === $scope.selectedIndex) ? -1 : ind;
}
$scope.getClass = function(ind){
return (ind === $scope.selectedIndex) ? "selected" : "";
}
$scope.getButtonLabel = function(ind){
return (ind === $scope.selectedIndex) ? "Deselect" : "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>
Это решение более лаконично и использует тернарные операторы для сокращения кода, что делает его легче для восприятия.
Я столкнулся с подобной проблемой недавно и решил просто создать условный фильтр:
angular.module('myFilters', []).
/**
* Фильтр "if"
* Простой фильтр, полезный для условного применения CSS-классов и декомпозиции
* представления от контроллера
*/
filter('if', function() {
return function(input, value) {
if (typeof(input) === 'string') {
input = [input, ''];
}
return value ? input[0] : input[1];
};
});
Этот фильтр принимает один аргумент, который может быть либо массивом из двух элементов, либо строкой. Если передана строка, она преобразуется в массив, к которому добавляется пустая строка в качестве второго элемента:
<li ng-repeat="item in products | filter:search | orderBy:orderProp |
page:pageNum:pageLength" ng-class="'opened' | if: isOpen(item)">
...
</li>
Таким образом, можно удобно управлять классами в зависимости от условия, что упрощает код и делает его более читаемым.
Получить координаты (X,Y) HTML-элемента
Как создать ненумерованный список без маркеров?
Стилизация кнопки input type="file"
Изменение цвета элемента hr
Использование подстановочного знака * в CSS для классов