如何在选择ng-options时使用ng-class

时间:2013-03-07 05:50:18

标签: select angularjs ng-class

我有一个Person对象数组

var persons = [
{Name:'John',Eligible:true},
{Name:'Mark',Eligible:true},
{Name:'Sam',Eligible:false},
{Name:'Edward',Eligible:false},
{Name:'Michael',Eligible:true}
];

我正在使用带有这样的ng-options的select:

<select ng-model="Blah" ng-options="person.Name for person in persons"></select>

我想以红色颜色显示符合条件:false 的记录。 所以问题是如何使用ng-class中的select来实现这一目标?由于我们没有使用任何option代码,因此我只需在ng-class元素中添加select就无法使用。

9 个答案:

答案 0 :(得分:33)

您可以创建一个指令,在处理ngOptions指令后处理这些选项,并使用适当的类更新它们。

更新:旧代码有一些错误,自从我回答这个问题以来,我学到了一些东西。 Here is a Plunk that was redone in 1.2.2 (but should work in 1.0.X as well)

以下已更新代码:

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-class类似,但除了它是基于每个项目的集合。

答案 1 :(得分:13)

在这种情况下,只有在ng-repeat使用选项标记时才能应用ng-class:

<select ng-model="Blah">
  <option ng-repeat="person in persons" ng-class="{red: person.Eligible}">{{person.Name}}</option>  
</select>

这将为您的“合格”人员提供自定义课程,但CSS不会在不同的人之间保持一致。

Plunker

答案 2 :(得分:4)

我想评论接受的答案,但由于我没有足够的声誉点,我必须添加一个答案。 我知道这是一个老问题,但是最近添加到已接受答案中的评论。

对于angularjs 1.4.x,必须调整建议的指令以使其再次工作。 由于ngOptions中的重大变化,选项的值不再是索引,因此行

option = elem.find('option[value=' + index + ']');

将不再有效。

如果您将plunker中的代码更改为

<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是项目对象的id)

将指令更改为

option = elem.find('option[value=\'number:' + item.id + '\']');

让它再次运作。

当然这不是一般的解决方案,因为如果你的对象中没有id怎么办? 然后,您会在选项标记中找到value="object:y",其中y是由angularjs生成的数字,但是使用此y,您无法映射到您的商品。

希望这可以帮助一些人在将angularjs更新到1.4.x之后再次使用他们的代码

我还尝试在ng-options中使用track by,但没有让它工作。 也许那些对angularjs有更多经验的人然后是我(=我在angularjs的第一个项目)?

答案 3 :(得分:3)

该指令是单向的,但我使用了自定义过滤器。 如果您知道如何选择元素,那么您应该没问题。挑战是在select中找到当前选项元素。我可以使用“包含”选择器,但选项中的文本可能不是唯一的项目。为了按值查找选项,我注入了范围和项目本身。

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

您可see it work

答案 4 :(得分:3)

接受的答案对我不起作用,所以我找到了一个没有使用track by的自定义指令的替代方案:

<select ng-model="foo" ng-options="x.name for x in items track by x.eligible"></select>

现在每个选项都获得x.eligible值。在CSS中,您可以使用value = true设置样式选项(我认为true必须是字符串)。 CSS:

option[value="true"]{
    color: red;
}

答案 5 :(得分:3)

如果您不仅希望以红色显示它们而阻止用户选择选项,您可以使用disable when

<select 
    ng-model="Blah"
    ng-options="person.Name disable when !person.Eligible for person in persons">
</select>

然后,您可以使用CSS设置禁用选项的颜色。

答案 6 :(得分:2)

由于声誉,我不能将此作为评论写出来,但我已更新了使用Angular 1.4.8的已接受答案的plunker。感谢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 :(得分:2)

我知道我参加派对有点晚了,但是对于想要用纯CSS解决这个问题的人来说,如果不使用指令,你可以像这样制作一个css类:

    select.blueSelect option[value="false"]{
    color:#01aac7;
}

此css规则说明:使用标记名称&#39;选项&#39;查找值为false的所有元素在每个人的内部选择&#39;有一个班级&#34; blueSelect&#34;并使文字颜色#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内部的轨道将保留跟踪选项的内容,或者&#34;值&#34;每个选项的字段。请注意,根据您的项目需求,您可能需要进行一些调整以使其按照您的要求工作。

但是,如果符合条件的字段具有相同值的多个选项,则无法正常工作。因此,为了使这项工作,我们创建一个复合表达式来跟踪,这样我们可以在每个选项中有唯一的值来跟踪。在这种情况下,我们将字段名称和合格

组合在一起

所以现在我们的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;
 }

注意值旁边的*,这是一个正则表达式,意思是找到单词&#34; False&#34;选项元素的值字段中的某个位置。

快速修改 您还可以选择使用&#34;禁用符合条件= False时禁用选项。在ng-options表达式中,例如:

标签 禁用 strong> 数组 跟踪 trackexpr

我将在你的案例中留下如何使用它来找出答案; - )

这适用于简单的CSS修改,对于更复杂的东西,您可能需要指令或其他方法。用铬测试。

我希望这可以帮助那些人。 : - )

答案 8 :(得分:-1)

我发现另一种解决方法比添加指令或过滤器更容易,这是为应用该样式的onfocus事件添加处理程序。

angular.element('select.styled').focus( function() {
  angular.element(this).find('option').addClass('myStyle');
});