使用AngularJS的ng-options选择


442

我已经在其他帖子中阅读过,但是我无法弄清楚。

我有一个数组

$scope.items = [
   {ID: '000001', Title: 'Chicago'},
   {ID: '000002', Title: 'New York'},
   {ID: '000003', Title: 'Washington'},
];

我想将其渲染为:

<select>
  <option value="000001">Chicago</option>
  <option value="000002">New York</option>
  <option value="000003">Washington</option>
</select>

我也想选择ID = 000002的选项。

我已经阅读了select并尝试过,但是我无法弄清楚。


我强烈建议您使用Select2,因为它将为您处理此事。甚至AngularJS的指令
hewstone


实际上,有一个由QuantumUI开发的纯AngularJS解决方案。您可以在http://quantumui.org/上找到更多示例和文档。
拉蒙·德伦斯

Answers:


799

需要注意的一件事是ngModel是ngOptions起作用所必需的...请注意ng-model="blah"

尝试这个:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

这里是AngularJS文档的更多内容(如果您还没有看过的话):

对于数组数据源:

  • 数组中值的标签
  • 选择作为数组中值的标签
  • 标签按组为数组中的值=选择标签按组为数组中的值

对于对象数据源:

  • 对象中(key,value)的标签
  • 选择作为对象中(key,value)的标签
  • 在对象中按组为(键,值)标签
  • 为对象中的(键,值)按组选择作为标签

对于AngularJS中的选项标签值的一些澄清:

使用时ng-optionsng-options写入的选项标签的值将始终是选项标签所关联的数组项的索引。这是因为AngularJS实际上允许您使用选择控件来选择整个对象,而不仅仅是原始类型。例如:

app.controller('MainCtrl', function($scope) {
   $scope.items = [
     { id: 1, name: 'foo' },
     { id: 2, name: 'bar' },
     { id: 3, name: 'blah' }
   ];
});
<div ng-controller="MainCtrl">
   <select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
   <pre>{{selectedItem | json}}</pre>
</div>

上面的内容使您可以$scope.selectedItem直接选择整个对象。关键是,使用AngularJS,您无需担心选项标签中的内容。让AngularJS处理;您应该只关心范围中模型的内容。

这是一个演示上述行为的插件,并显示了写出的HTML


处理默认选项:

上面我没有提到与默认选项有关的几件事。

选择第一个选项并删除空选项:

您可以通过添加一个简单ng-init的模型来实现此目的,该模型将模型(from ng-model)设置为您在其中重复的项目中的第一个元素ng-options

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.name for item in items"></select>

注意:如果foo恰好正确初始化为“ fassy”,这可能会有点疯狂。在这种情况下,您foo很可能希望在控制器中处理的初始化。

自定义默认选项:

这有点不同。在这里,您所需要做的就是添加一个选择标签作为您选择的子标签,并带有一个空值属性,然后自定义其内部文本:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="">Nothing selected</option>
</select>

注意:在这种情况下,即使您选择其他选项,“空”选项也将保留在那里。AngularJS下selects的默认行为不是这种情况。

一个定制的默认选项,在选择之后会隐藏:

如果希望在选择一个值后取消自定义的默认选项,则可以在默认选项中添加ng-hide属性:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="" ng-if="foo">Select something to remove me.</option>
</select>

3
原来,这些是值的索引,这就是角度如何允许您将对象用作选择框的值。Angular通过选择框在幕后为您做很多事情,您不必担心选项的value属性。
Ben Lesh 2012年

1
文档位于其网站上的“选择”下:docs.angularjs.org/api/ng.directive
Ben Lesh

25
“ ... ngModel是ngOptions工作所必需的...”对我来说是问题的症结所在。好答案。
tristanm

1
是否可以避免第一个空选项(<option value="?" selected="selected"></option>)?
swenedo 2013年

4
我正在尝试使用最后一种情况(做出选择后隐藏的自定义默认选项),但是发现了一些问题。当选择其他选项时,ng-if="foo"我不得不使用它ng-if=!foo来隐藏默认的空选项。此外,默认的空选项始终显示在组合列表的底部。如何将其放在组合列表的开头?
Fran Herrero

90

我正在学习AngularJS,并且在选择方面也很挣扎。我知道这个问题已经回答了,但是我仍然想共享更多代码。

在测试中,我有两个列表框:汽车制造商和汽车模型。在选择某些品牌之前,型号列表将被禁用。如果稍后重新设置制造商列表框中的选择(设置为“选择制造商”),则型号列表框将再次被禁用,并且其选择也将被重置(设置为“选择模型”)。在仅对模型进行硬编码的同时,将Makes作为资源检索。

制作JSON:

[
{"code": "0", "name": "Select Make"},
{"code": "1", "name": "Acura"},
{"code": "2", "name": "Audi"}
]

services.js:

angular.module('makeServices', ['ngResource']).
factory('Make', function($resource){
    return $resource('makes.json', {}, {
        query: {method:'GET', isArray:true}
    });
});

HTML档案:

<div ng:controller="MakeModelCtrl">
  <div>Make</div>
  <select id="makeListBox"
      ng-model="make.selected"
      ng-options="make.code as make.name for make in makes"
      ng-change="makeChanged(make.selected)">
  </select>

  <div>Model</div>
  <select id="modelListBox"
     ng-disabled="makeNotSelected"
     ng-model="model.selected"
     ng-options="model.code as model.name for model in models">
  </select>
</div>

controllers.js:

function MakeModelCtrl($scope)
{
    $scope.makeNotSelected = true;
    $scope.make = {selected: "0"};
    $scope.makes = Make.query({}, function (makes) {
         $scope.make = {selected: makes[0].code};
    });

    $scope.makeChanged = function(selectedMakeCode) {
        $scope.makeNotSelected = !selectedMakeCode;
        if ($scope.makeNotSelected)
        {
            $scope.model = {selected: "0"};
        }
    };

    $scope.models = [
      {code:"0", name:"Select Model"},
      {code:"1", name:"Model1"},
      {code:"2", name:"Model2"}
    ];
    $scope.model = {selected: "0"};
}

27
尊敬的随机用户。虽然这个问题及其答案非常简单且不复杂,但是将代码组织到正确的位置和相应的位置(控制器,服务,模板,数据),以最简单和默认的形式展示了AngularJS的优雅之处。很棒的例子。
阿提克斯

1
这不是要使用的方式。ng-model应该指向您范围内与无关的另一个变量make。请参阅docs.angularjs.org/api/ng/directive/ngOptions中
Dmitri Zaitsev

@DmitriZaitsev我认为您是错误的,仅因为有角度的文档示例以您描述的方式显示了它,但这并不意味着那是唯一的方法。向我们展示为什么您认为不应该以这种方式使用它,而不是给新手打个好榜样。
JRT 2015年

39

由于某些原因,AngularJS会让我感到困惑。他们的文档对此非常恐怖。欢迎提供更多更好的变体示例。

无论如何,我对本·莱什的回答略有不同。

我的数据收集如下所示:

items =
[
   { key:"AD",value:"Andorra" }
,  { key:"AI",value:"Anguilla" }
,  { key:"AO",value:"Angola" }
 ...etc..
]

现在

<select ng-model="countries" ng-options="item.key as item.value for item in items"></select>

仍然导致选项值成为索引(0、1、2等)。

为我添加Track By修复:

<select ng-model="blah" ng-options="item.value for item in items track by item.key"></select>

我认为这种情况经常发生,您想将一组对象添加到选择列表中,所以我要记住这一点!

请注意,从AngularJS 1.4开始,您不能再使用ng-options了,但是需要ng-repeat在option标签上使用:

<select name="test">
   <option ng-repeat="item in items" value="{{item.key}}">{{item.value}}</option>
</select>

3
这个答案似乎正是这个问题所要的。其他所有答案都告诉读者不要担心会生成什么HTML,但是如果select元素采用某种形式,我会非常担心。好答案!
基思

3
应该指出的是,这会将完整的选定对象存储在模型中,而不仅仅是键。如果只需要模型中的键,则要使用“ item.key作为item.value”版本。这让我有些困惑,因为我迷上了HTML的外观,而不是模型中想要的数据,这对我来说很重要。
mhenry1384 2015年

@ mhenry1384是的,对了,它存储了整个对象。我实际上喜欢该功能,因为它使您不仅可以访问ID(如果需要),还可以访问它。当我用mongo集合填充列表并且我需要所选项目的一些属性时,对我来说效果很好。
马蒂斯

2
以及如何通过内部的“ ng-change”来检测变化option
Konstantinos Natsios

2
关于更新,这看起来不正确。ng-options在1.5中仍然可以正常工作。它仍然显示在文档中。 docs.angularjs.org/api/ng/directive/select
杰里米·A·韦斯特

15

这个问题已经回答了(顺便说一句,Ben确实提供了很好的综合答案),但是我想补充一点完整性,这也可能非常方便。

在Ben建议的示例中:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

以下 ngOptions表单:select as label for value in array

Label是一个表达式,其结果将是<option> element。在这种情况下,您可以执行某些字符串连接,以具有更复杂的选项标签。

例子:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" 给你像 Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items"为您提供标签,如Title (X),其中XTitle字符串的长度。

您还可以使用过滤器,例如,

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items" 给你像 Title (TITLE),其中Title属性的Title值和TITLE是相同的值,但转换为大写字符。
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items"为您提供标签,例如Title (27 Sep 2015),如果您的模型具有属性SomeDate

7

在CoffeeScript中:

#directive
app.directive('select2', ->
    templateUrl: 'partials/select.html'
    restrict: 'E'
    transclude: 1
    replace: 1
    scope:
        options: '='
        model: '='
    link: (scope, el, atr)->
        el.bind 'change', ->
            console.log this.value
            scope.model = parseInt(this.value)
            console.log scope
            scope.$apply()
)
<!-- HTML partial -->
<select>
  <option ng-repeat='o in options'
          value='{{$index}}' ng-bind='o'></option>
</select>

<!-- HTML usage -->
<select2 options='mnuOffline' model='offlinePage.toggle' ></select2>

<!-- Conclusion -->
<p>Sometimes it's much easier to create your own directive...</p>

1
不要忘记您的radix帮助parseInthttp
//davidwalsh.name/parseint-radix

6

如果每个选项都需要自定义标题,ng-options则不适用。而是ng-repeat与选项一起使用:

<select ng-model="myVariable">
  <option ng-repeat="item in items"
          value="{{item.ID}}"
          title="Custom title: {{item.Title}} [{{item.ID}}]">
       {{item.Title}}
  </option>
</select>

3

希望以下内容对您有用。

<select class="form-control"
        ng-model="selectedOption"
        ng-options="option.name + ' (' + (option.price | currency:'USD$') + ')' for option in options">
</select>

1

这可能是有用的。绑定并不总是有效。

<select id="product" class="form-control" name="product" required
        ng-model="issue.productId"
        ng-change="getProductVersions()"
        ng-options="p.id as p.shortName for p in products"></select>

例如,您从REST服务填充选项列表源模型。在填充列表之前,已知道所选值,并且已设置该值。用$ http执行REST请求后,list选项就完成了。

但是未设置所选选项。由于未知原因,阴影$ digest执行中的AngularJS不会按原样绑定选择。我必须使用jQuery设置所选内容。重要!阴影中的AngularJS将前缀添加到由ng-repeat选项生成的attr“值”的值。对于int,它是“数字:”。

$scope.issue.productId = productId;
function activate() {
    $http.get('/product/list')
       .then(function (response) {
           $scope.products = response.data;

           if (productId) {
               console.log("" + $("#product option").length);//for clarity
               $timeout(function () {
                   console.log("" + $("#product option").length);//for clarity
                   $('#product').val('number:'+productId);

               }, 200);
           }
       });
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.