Как использовать ng-класс в select с ng-options
У меня есть массив объектов Person
var persons = [
{Name:'John',Eligible:true},
{Name:'Mark',Eligible:true},
{Name:'Sam',Eligible:false},
{Name:'Edward',Eligible:false},
{Name:'Michael',Eligible:true}
];
и я использую select с параметрами ng, например:
<select ng-model="Blah" ng-options="person.Name for person in persons"></select>
Я хочу показать запись с допустимым: false в цвете красного.
Итак, проблема в том, как я могу использовать ng-class
in select
inorder для достижения этого? Поскольку мы не используем тег option
, он не будет работать, если я просто добавлю ng-class
в сам элемент select
.
Ответы
Ответ 1
Вы можете создать директиву, которая обрабатывала параметры после обработки директивы ngOptions, которая обновляла их соответствующими классами.
Обновить. У старого кода было несколько ошибок, и я немного узнал, так как я ответил на этот вопрос. Вот Plunk, который был переделан в 1.2.2 (но должен работать и в 1.0.X)
Здесь обновлен Код:
app.directive('optionsClass', function ($parse) {
return {
require: 'select',
link: function(scope, elem, attrs, ngSelect) {
// get the source for the items array that populates the select.
var optionsSourceStr = attrs.ngOptions.split(' ').pop(),
// use $parse to get a function from the options-class attribute
// that you can use to evaluate later.
getOptionsClass = $parse(attrs.optionsClass);
scope.$watch(optionsSourceStr, function(items) {
// when the options source changes loop through its items.
angular.forEach(items, function(item, index) {
// evaluate against the item to get a mapping object for
// for your classes.
var classes = getOptionsClass(item),
// also get the option you're going to need. This can be found
// by looking for the option with the appropriate index in the
// value attribute.
option = elem.find('option[value=' + index + ']');
// now loop through the key/value pairs in the mapping object
// and apply the classes that evaluated to be truthy.
angular.forEach(classes, function(add, className) {
if(add) {
angular.element(option).addClass(className);
}
});
});
});
}
};
});
Здесь вы можете использовать его в своей разметке:
<select ng-model="foo" ng-options="x.name for x in items"
options-class="{ 'is-eligible' : eligible, 'not-eligible': !eligible }"></select>
Он работает, как и ng-класс, за исключением того, что он основан на каждом элементе в коллекции.
Ответ 2
В этом сценарии вы можете применить только ng-класс, только если вы используете ng-repeat
с тегами опций:
<select ng-model="Blah">
<option ng-repeat="person in persons" ng-class="{red: person.Eligible}">{{person.Name}}</option>
</select>
Это предоставит пользовательский класс вашим "правомочным" лицам, но CSS не будет работать последовательно между баустерами.
Plunker.
Ответ 3
Я хотел прокомментировать принятый ответ, но поскольку у меня недостаточно очков репутации, я должен добавить ответ.
Я знаю, что это старый вопрос, но комментарии, недавно добавленные к принятому ответу.
Для угловых 1.4.x предлагаемая директива должна быть адаптирована, чтобы заставить ее снова работать.
Из-за разрыва в ngOptions значение параметра больше не является индексом, поэтому строка
option = elem.find('option[value=' + index + ']');
больше не будет работать.
Если вы измените код в плункере на
<select ng-model="foo" ng-options="x.id as x.name for x in items"
options-class="{ 'is-eligible' : eligible, 'not-eligible': !eligible }"></select>
В результате значение тега опции будет
value="number:x"
(x - это идентификатор объекта элемента)
Измените директиву на
option = elem.find('option[value=\'number:' + item.id + '\']');
чтобы он снова работал.
Конечно, это не общее решение, потому что, если у вас нет идентификатора в вашем объекте?
Затем вы найдете value="object:y"
в своем теге параметров, где y - число, сгенерированное угловыми, но с этим y
вы не можете сопоставить свои объекты.
Надеется, что это поможет некоторым людям снова получить свой код, работающий после обновления angularjs до 1.4.x
Я также попытался использовать track by
в ng-опциях, но не смог заставить его работать.
Может быть, люди с большим опытом в angularjs, тогда я (= мой первый проект в angularjs)?
Ответ 4
Директива - это один из способов, но я использовал собственный фильтр.
Если вы знаете, как выбрать свой элемент, вы должны быть в порядке. Задача заключалась в том, чтобы найти текущий элемент опции внутри select. Я мог бы использовать селектор "contains", но текст в параметрах может быть не уникальным для элементов. Чтобы найти параметр по значению, я ввел область и сам элемент.
<select ng-model="foo" ng-options="item.name|addClass:{eligible:item.eligible,className:'eligible',scope:this,item:item} for item in items"></select>
и в js:
var app = angular.module('test', []);
app.filter('addClass', function() {
return function(text, opt) {
var i;
$.each(opt.scope.items,function(index,item) {
if (item.id === opt.item.id) {
i = index;
return false;
}
});
var elem = angular.element("select > option[value='" + i + "']");
var classTail = opt.className;
if (opt.eligible) {
elem.addClass('is-' + classTail);
elem.removeClass('not-' + classTail);
} else {
elem.addClass('not-' + classTail);
elem.removeClass('is-' + classTail);
}
return text;
}
})
app.controller('MainCtrl', function($scope) {
$scope.items = [
{ name: 'foo',id: 'x1',eligible: true},
{ name: 'bar',id: 'x2',eligible: false},
{ name: 'test',id: 'x3',eligible: true}
];
});
Здесь вы можете видеть, как он работает.
Ответ 5
Принятый ответ не работал у меня, поэтому я нашел альтернативу без пользовательской директивы, используя track by
:
<select ng-model="foo" ng-options="x.name for x in items track by x.eligible"></select>
Каждая опция теперь получает значение x.eligible. В CSS вы можете настраивать параметры со значением = true (я думаю, что истина должна быть строкой). CSS:
option[value="true"]{
color: red;
}
Ответ 6
Я не могу написать это как комментарий из-за репутации, но я обновил плункер для принятого ответа на работу с Angular 1.4.8. Благодаря Ben Lesh для первоначального ответа мне это очень помогло. Разница заключается в том, что новый Angular генерирует такие параметры:
<option class="is-eligible" label="foo" value="object:1">foo</option>
поэтому код
option = elem.find('option[value=' + index + ']');
не сможет найти эту опцию. Мое изменение анализирует ngOptions и определяет, какое поле элемента было использовано для метки, и находит опцию на основе этого вместо значения. См:
http://plnkr.co/edit/MMZfuNZyouaNGulfJn41
Ответ 7
Если вы не хотите показывать их только красным цветом, но не позволяете пользователю выбирать параметры, вы можете использовать disable when
:
<select
ng-model="Blah"
ng-options="person.Name disable when !person.Eligible for person in persons">
</select>
Затем вы можете использовать CSS для установки цвета отключенных параметров.
Ответ 8
Я знаю, что я немного опаздываю на вечеринку, но для людей, которые хотят решить это с помощью чистого CSS, без использования директивы вы можете создать класс css следующим образом:
select.blueSelect option[value="false"]{
color:#01aac7;
}
Это правило css говорит: найдите все элементы со значением = false с именем тега 'option' внутри каждого "select", который имеет класс "blueSelect" и сделайте цвет текста # 01aac7; (оттенок синего)
В вашем случае ваш HTML будет выглядеть так:
<select class="form-control blueSelect" name="persons" id="persons1"
ng-options="person as person.name for person in $ctrl.persons track by person.Eligible"
ng-model="$ctrl.selectedPerson" required>
<option disabled selected value="">Default value</option>
</select>
Трек внутри ng-options - это то, что будет содержать то, что отслеживать параметры, или поле "значение" для каждой опции. Обратите внимание, что в зависимости от потребностей вашего проекта вам, возможно, придется сделать некоторые настройки, чтобы эта работа соответствовала вашим требованиям.
Но это не сработает правильно, если имеется несколько опций с одинаковым значением для поля "Доступно". Поэтому для создания этой работы мы создаем составное выражение для отслеживания, таким образом, у нас могут быть уникальные значения для отслеживания по каждому параметру. В этом случае мы объединяем оба поля Name и Allow
Итак, теперь наш html будет выглядеть следующим образом
<select class="form-control blueSelect" name="persons" id="persons2"
ng-options="person as person.name for person in $ctrl.persons track by (person.name + person.Eligible)"
ng-model="$ctrl.selectedPerson" required>
<option disabled selected value="">Default value</option>
</select>
и наш css:
select.blueSelect option[value*="False"]{
color:#01aac7;
}
Обратите внимание на * рядом со значением, это регулярное выражение, которое означает найти слово "False" где-нибудь в поле значения элемента option.
Быстрое редактирование
Вы также можете отключить опции с допустимым = False, используя "отключить когда" в выражении ng-options, например:
label отключить, когда отключить для значение в массив отслеживать trackexpr
Я оставлю, как использовать это в вашем случае, чтобы вы узнали; -)
Это работает для простых модификаций css, для более сложных вещей вам может понадобиться директива или другие методы. Протестировано в хроме.
Я надеюсь, что это поможет кому-то там.: -)