12

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

12

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

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

5 ответ(ов)

13

Если вы не хотите помещать имена 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-классы из кода контроллера.

1

Мой любимый способ — использование тернарного оператора.

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

Примечание: Если вы используете более старую версию Angular, вам следует использовать следующий подход:

ng-class="condition && 'trueClass' || 'falseClass'"
0

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

<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

0

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

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>

Это решение более лаконично и использует тернарные операторы для сокращения кода, что делает его легче для восприятия.

0

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

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>

Таким образом, можно удобно управлять классами в зависимости от условия, что упрощает код и делает его более читаемым.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь