2013-03-07 50 views
33

我个人的对象数组如何使用纳克级的选择与NG选项

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

,我使用选择与NG选项是这样的:

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

我想以显示记录合格:虚假红色颜色。 所以问题是我如何使用ng-classselect为了达到这个目的?由于我们没有使用任何option标签,因此如果我简单地在select元素本身中添加ng-class,它将无法正常工作。

+0

使用指令循环选项,并将类应用于选项标签,满足条件 – charlietfl 2013-03-07 06:46:54

+0

是的,我可以做到这一点,但没有任何方式直接做到这一点?我的意思是在这里必须有一种方法来使用ng-class。 – 2013-03-07 08:12:10

+0

供参考:我已经更新了我的答案,因为它有一些错误。不知道这是否会影响当前代码库中的任何内容,但是如果您在使用之前发布的内容,可能需要查看一下。 – 2013-11-30 03:18:16

回答

30

您可以创建一个指令,在处理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> 

它就像纳克级呢,不同之处在于它在每个项目收集的基础上。

+1

这是一个很好的解决方案使用。总有一些指令可以挽救一天! :D +1 – 2013-03-08 03:38:29

+1

这是一个有趣的想法。我喜欢参加创建新范围的地方,并将其与我正在研究的孩子一起扩展,以便我可以评估它!所以Angular非常有角度。当我编码时,让我想要发出激光声音... pew pew pew。 – 2013-03-08 18:08:28

+0

blesh,你的指令无法正常工作。在选择任何

12

在这种情况下,你只能申请纳克级只有在使用ng-repeat与选项标签:

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

这将使自定义类到您的“合格”的人,但CSS不会一致地工作bowsers。

Plunker

+1

这个工程,但我想用ng选项,因为这不会让任何值选择一次,我将它保存在我的数据库并刷新它。你有什么想法如何保持我的纪录选择?我已经使用ng选择了这个,但是也不会工作 – 2013-03-07 10:30:01

+0

这不是问题。我将Plunker链接附加到答案上。 – Stewie 2013-03-07 10:38:37

+0

谢谢你!我正在使用相同的东西。只有不同的是我使用jQuery版本-1.7,因此它不支持ng选择。改变了版本参考,它的作品奇迹! – 2013-03-07 12:18:19

3

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

<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

+1

实际上只是将项目集合发送到过滤器(通过您的范围对象)。使用像这样的索引 对于项目中的(idx,item)项目,您可以删除$。如果你的收藏很大,这可能会造成浪费。你的元素找到现在这个 - var elem = angular.element(“select> option [value ='”+ opt.ix +“']”); 感谢您的回答,我最终使用它与我的国防部。 – Craig 2014-11-25 03:04:06

+0

是的,你说得对,谢谢你的建议。正如我提出的那样,我并不知道,通常过滤器的价格是多少,通过参数注入的范围并不是最佳实践的一部分。 – westor 2014-11-25 16:36:34

+0

我不会为此使用过滤器。通常过滤器也需要在服务和控制器中使用。做DOM操作打破了这一点。指令是为此而设计的。 – Dormouse 2014-12-15 11:15:25

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; 
} 
+0

谢谢!我会试试这个。 – 2014-09-23 09:02:35

+0

这是否会触发重复的项目错误,因为符合条件的项目必须是唯一的?所以这不会工作布尔以外的数据(是/否选择)。 – Dormouse 2014-12-15 11:12:40

+0

适用于某些数据类型的简单解决方案。 – chris22smith 2017-01-23 11:14:28

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-选项track by,但没有得到它的工作。 也许有更多的经验,在angularjs然后我(=我的第一个项目在angularjs)?

2

由于声誉的原因,我无法将其作为评论来撰写,但我已经更新了与Angular 1.4.8一起使用的公开答案。感谢Ben Lesh提供的原始答案,这对我有很大的帮助。所不同的似乎是较新的角度产生的选项是这样的:

<option class="is-eligible" label="foo" value="object:1">foo</option> 

所以代码

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

将无法​​找到的选项。我的更改解析了ngOptions并确定了该标签使用的项目的哪个字段,并根据该选项找到了代替值的选项。请参阅:

http://plnkr.co/edit/MMZfuNZyouaNGulfJn41

2

如果你既想显示他们在红颜色,但防止用户选择的选项,你可以使用disable when

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

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

2

我知道我有点迟到了,但谁不想用纯CSS来解决这个问题,不使用指令的人,你可以做一个CSS类是这样的:

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

这个CSS规则说:找到所有具有值=假的标签名称为'选项'的每个'选择'中有一个类“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选项里面的曲目是什么将举行什么来跟踪的选项,或“值“每个选项的字段。请注意,根据您的项目需求,您可能需要做一些调整才能按照您的要求进行此项工作。

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

所以,现在我们的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”。

快速编辑 您也可以选择禁用与合格=使用虚假的选项“禁用时”中的NG选项表达,例如:

标签禁用时禁用阵列轨道由trackexpr

我会留下怎样使用你的情况为你找出;-)

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

我希望这可以帮助一个人在那里。 :-)