566

这似乎困扰着很多人(包括我)。

在使用ng-optionsAngularJS 中的指令填充<select>标签的选项时,我无法弄清楚如何设置选项的值。这方面的文档真的不清楚 - 至少对于像我这样的傻瓜来说。

我可以像这样轻松地为选项设置文本:

ng-options="select p.text for p in resultOptions"

resultOptions例如什么时候:

[
    {
        "value": 1,
        "text": "1st"
    },
    {
        "value": 2,
        "text": "2nd"
    }
]

设置选项值应该是(并且可能是)最简单的事情,但到目前为止我还是不明白。

4

27 回答 27

711

ngOptions

ngOptions(optional) – { comprehension_expression=} – 以下形式之一:

对于数组数据源label for value in array select as label for value in array label group by group for value in array select as label group by group for value in array track by trackexpr 对于对象数据源: label for (key , value) in object select as label for (key , value) in object label group by group for (key, value) in object select as label group by group for (key, value) in object

在你的情况下,它应该是

array = [{ "value": 1, "text": "1st" }, { "value": 2, "text": "2nd" }];

<select ng-options="obj.value as obj.text for obj in array"></select>

更新

随着 AngularJS 的更新,现在可以为带有表达式的元素的value属性设置实际值。selecttrack by

<select ng-options="obj.text for obj in array track by obj.value">
</select>

如何记住这些丑陋的东西

对于所有难以记住这种语法形式的人:我同意这不是最简单或最漂亮的语法。这种语法是 Python 列表推导的一种扩展版本,并且知道这有助于我很容易地记住语法。是这样的:

Python代码:

my_list = [x**2 for x in [1, 2, 3, 4, 5]]
> [1, 4, 9, 16, 25]

# Let people to be a list of person instances
my_list2 = [person.name for person in people]
> my_list2 = ['Alice', 'Bob']

这实际上与上面列出的第一个语法相同。但是,<select>我们通常需要区分代码中的实际值和<select>元素中显示的文本(标签)。

就像,我们需要person.id在代码中,但我们不想向id用户显示;我们想显示它的名字。同样,我们对person.name代码中的 不感兴趣。有as关键字来标记东西。所以它变成了这样:

person.id as person.name for person in people

或者,person.id我们可能需要person实例/引用本身,而不是。见下文:

person as person.name for person in people

对于 JavaScript 对象,同样的方法也适用。请记住,对象中的项目是用(key, value)对解构的。

于 2012-08-27T10:33:05.293 回答
138

值属性如何获取其值:

  • 使用数组作为数据源时,每次迭代都会是数组元素的索引;
  • 当使用对象作为数据源时,它将是每次迭代中的属性名称。

所以在你的情况下应该是:

obj = { '1': '1st', '2': '2nd' };

<select ng-options="k as v for (k,v) in obj"></select>
于 2012-09-12T08:44:07.083 回答
123

我也有这个问题。我无法在 ng-options 中设置我的值。生成的每个选项都设置为 0、1、...、n。

为了使它正确,我在我的 ng-options 中做了这样的事情:

HTML:

<select ng-options="room.name for room in Rooms track by room.price">
    <option value="">--Rooms--</option>
</select>

我使用“track by”来设置我的所有值room.price

(这个例子很糟糕:因为如果有多个相同的价格,代码就会失败。所以请确保有不同的值。)

JSON:

$scope.Rooms = [
            { name: 'SALA01', price: 100 },
            { name: 'SALA02', price: 200 },
            { name: 'SALA03', price: 300 }
        ];

我从博客文章How to set the initial selected value of a select element using Angular.JS ng-options & track by 中了解到

观看视频。这是一堂很好的课:)

于 2014-04-10T19:17:37.867 回答
47

如果您想更改option元素的值,因为表单最终将提交到服务器,而不是这样做,

<select name="text" ng-model="text" ng-options="select p.text for p in resultOptions"></select>

你可以这样做:

<select ng-model="text" ng-options="select p.text for p in resultOptions"></select>
<input type="hidden" name="text" value="{{ text }}" />

然后将通过正确名称的表单发送预期值。

于 2013-06-12T16:35:04.873 回答
26

my_hero要使用普通表单提交将调用的自定义值发送到服务器:

JSON:

"heroes": [
  {"id":"iron", "label":"Iron Man Rocks!"},
  {"id":"super", "label":"Superman Rocks!"}
]

HTML:

<select ng-model="hero" ng-options="obj.id as obj.label for obj in heroes"></select>
<input type="hidden" name="my_hero" value="{{hero}}" />

服务器将接收ironsuper作为 的值my_hero

这类似于@neemzy 的答案value,但为属性指定了单独的数据。

于 2013-11-28T19:00:06.267 回答
24

看起来使用起来ng-options很复杂(可能令人沮丧),但实际上我们遇到了架构问题。

AngularJS 用作动态 HTML+JavaScript 应用程序的 MVC 框架。虽然它的 (V)iew 组件确实提供了 HTML“模板”,但它的主要目的是通过控制器将用户操作与模型中的更改联系起来。因此,在 AngularJS 中工作的适当抽象级别是 select 元素将模型中的值设置为来自查询的值

  • 查询行如何呈现给用户是 (V)iew 的关注点,并ng-options提供for关键字来指示选项元素的内容应该是什么, p.text for p in resultOptions.
  • 如何将选定的行呈现给服务器是 (M) 模型的关注点。因此ng-options提供as关键字来指定向模型提供什么值,如k as v for (k,v) in objects.

这个问题的正确解决方案本质上是架构性的,并且涉及重构您的 HTML,以便 (M) 模型在需要时执行服务器通信(而不是用户提交表单)。

如果一个 MVC HTML 页面对于手头的问题是不必要的过度工程:那么只使用 AngularJS 的 (V)iew 组件的 HTML 生成部分。在这种情况下,请遵循用于生成元素(例如&lt;li /&gt;'s under &lt;ul /&gt;'s)的相同模式,并在选项元素上放置一个 ng-repeat:

<select name=“value”&gt;
    <option ng-repeat=“value in Model.Values” value=“{{value.value}}”&gt;
        {{value.text}}
    </option>
</select>

作为kludge,总是可以将 select 元素的 name 属性移动到隐藏的 input 元素:

<select ng-model=“selectedValue” ng-options=“value.text for value in Model.Values”&gt;
</select>
<input type=“hidden” name=“value” value=“{{selectedValue}}” />
于 2013-11-16T23:06:15.433 回答
20

你可以这样做:

<select ng-model="model">
    <option value="">Select</option>
    <option ng-repeat="obj in array" value="{{obj.id}}">{{obj.name}}</option>
</select>

- 更新

经过一些更新,用户frm.adiputra的解决方案要好得多。代码:

obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>
于 2012-11-01T19:00:32.790 回答
14

我今天已经为这个问题苦苦挣扎了一段时间。我通读了 AngularJS 文档、这篇文章和其他文章,以及他们引出的一些博客。他们都帮助我了解了更精细的细节,但最终这似乎是一个令人困惑的话题。主要是因为ng-options.

最后,对我来说,它归结为少即是多。

给定一个配置如下的范围:

        //Data used to populate the dropdown list
        $scope.list = [
           {"FirmnessID":1,"Description":"Soft","Value":1},         
           {"FirmnessID":2,"Description":"Medium-Soft","Value":2},
           {"FirmnessID":3,"Description":"Medium","Value":3}, 
           {"FirmnessID":4,"Description":"Firm","Value":4},     
           {"FirmnessID":5,"Description":"Very Firm","Value":5}];

        //A record or row of data that is to be save to our data store.
        //FirmnessID is a foreign key to the list specified above.
        $scope.rec = {
           "id": 1,
           "FirmnessID": 2
        };

这就是我获得所需结果所需的全部内容:

        <select ng-model="rec.FirmnessID"
                ng-options="g.FirmnessID as g.Description for g in list">
            <option></option>
        </select>   

注意我没有使用track by. 使用track by所选项目将始终返回与 FirmnessID 匹配的对象,而不是 FirmnessID 本身。这现在符合我的标准,即它应该返回一个数值而不是对象,并用于ng-options通过不为生成的每个选项创建新范围来获得它提供的性能改进。

另外,我需要空白的第一行,所以我只是<option><select>元素中添加了一个。

这是一个展示我工作的Plunkr

于 2015-05-17T20:04:12.230 回答
11

如果您希望值与文本相同,则无需使用新的“track by”功能,您只需使用数组即可:

<select ng-options="v as v for (k,v) in Array/Obj"></select>

注意标准语法之间的区别,这将使值成为对象/数组的键,因此数组的 0、1、2 等:

<select ng-options"k as v for (k,v) in Array/Obj"></select>

k as v变成v as v

我发现这只是基于查看语法的常识。(k,v) 是将数组/对象拆分为键值对的实际语句。

在“k as v”语句中,k 是值,v 是显示给用户的文本选项。我认为“跟踪”是混乱和矫枉过正。

于 2014-08-20T12:23:17.123 回答
11

根据我的说法,这最适合所有场景:

<select ng-model="mySelection.value">
   <option ng-repeat="r in myList" value="{{r.Id}}" ng-selected="mySelection.value == r.Id">{{r.Name}}
   </option>
</select>

您可以在其中使用模型来绑定数据。您将获得对象将包含的值以及基于您的方案的默认选择。

于 2015-06-04T13:22:41.050 回答
9

这就是我解决这个问题的方法。我跟踪了按值选择,并在我的 JavaScript 代码中将选定项属性设置为模型。

Countries =
[
    {
        CountryId = 1, Code = 'USA', CountryName = 'United States of America'
    },
    {
       CountryId = 2, Code = 'CAN', CountryName = 'Canada'
    }
]
<select ng-model="vm.Enterprise.AdminCountry" ng-options="country.CountryName for country in vm.Countries track by country.CountryId">

vm是我的控制器,从服务中检索到的控制器中的 Country 是{CountryId =1, Code = 'USA', CountryName='United States of America'}.

当我从选择下拉列表中选择另一个国家并使用“保存”发布我的页面时,我得到了正确的国家绑定。

于 2014-09-25T19:52:53.237 回答
8

ng-options指令没有<options>为数组的元素设置 value 属性:

使用limit.value as limit.text for limit in limits手段:

<option>'标签设置为limit.text
limit.value值保存到选择中ng-model

请参阅 Stack Overflow 问题AngularJS ng-options not rendering values

于 2013-07-01T07:42:49.520 回答
6

可以使用 ng-options 实现选择标签绑定到值和显示成员

使用此数据源时

countries : [
              {
                 "key": 1,
                 "name": "UAE"
             },
              {
                  "key": 2,
                  "name": "India"
              },
              {
                  "key": 3,
                  "name": "OMAN"
              }
         ]

您可以使用以下内容将您的选择标签绑定到值和名称

<select name="text" ng-model="name" ng-options="c.key as c.name for c in countries"></select>

效果很好

于 2017-12-19T16:20:58.080 回答
5
<select ng-model="color" ng-options="(c.name+' '+c.shade) for c in colors"></select><br>
于 2013-12-03T15:59:10.773 回答
4

问题提出一年后,我不得不为这个问题找到答案,因为至少对我来说,这些都没有给出实际答案。

您已经问过如何选择该选项,但没有人说这两件事一样:

如果我们有这样的选择:

$scope.options = [
    { label: 'one', value: 1 },
    { label: 'two', value: 2 }
  ];

我们尝试设置一个默认选项,如下所示:

$scope.incorrectlySelected = { label: 'two', value: 2 };

不起作用,但如果您尝试选择这样的选项:

$scope.correctlySelected = $scope.options[1];

它会工作

即使这两个对象具有相同的属性,AngularJS 仍将它们视为不同的,因为 AngularJS 通过引用进行比较。

看看小提琴http://jsfiddle.net/qWzTb/

于 2014-04-02T08:00:57.273 回答
3

用户frm.adiputra提供了这个问题的正确答案,因为目前这似乎是显式控制选项元素的 value 属性的唯一方法。

但是,我只是想强调一下,“select”在这种情况下不是关键字,而只是表达式的占位符。请参考下面的列表,以了解“select”表达式的定义以及可以在 ng-options 指令中使用的其他表达式。

问题中描述的 select 的使用:

ng-options='select p.text for p  in resultOptions'

本质上是错误的。

根据表达式列表,当在对象数组中给出选项时,似乎trackexpr可用于指定值,但它仅用于分组。


来自 AngularJS 的 ng-options 文档:

  • array / object : 一个表达式,其计算结果为要迭代的数组/对象。
  • value:局部变量,它将在迭代期间引用数组中的每个项目或对象的每个属性值。
  • key:局部变量,它将在迭代期间引用对象中的属性名称。
  • label:此表达式的结果将是元素的标签。表达式很可能引用值变量(例如 value.propertyName)。
  • select:此表达式的结果将绑定到父元素的模型。如果未指定,则选择表达式将默认为值。
  • group:此表达式的结果将用于使用 DOM 元素对选项进行分组。
  • trackexpr:在处理对象数组时使用。此表达式的结果将用于识别数组中的对象。trackexpr 很可能会引用 value 变量(例如 value.propertyName)。
于 2013-11-07T06:06:29.573 回答
3

根据您设置数据源的方式,在 ng-options 中选择一个项目可能会有些棘手。

在与他们斗争了一段时间后,我最终用我使用的最常见的数据源制作了一个样本。你可以在这里找到它:

http://plnkr.co/edit/fGq2PM?p=preview

现在要使 ng-options 工作,这里有一些事情需要考虑:

  1. 通常,您从一个来源获得选项,从另一个来源获得选定的值。例如:
    • 状态 :: ng-options 的数据
    • user.state :: 设置为选中的选项
  2. 基于1,最简单/合乎逻辑的做法是用一个源填充选择,然后通过代码设置选择的值。获得混合数据集很少会更好。
  3. AngularJS 允许选择控件容纳超过key | label. 许多在线示例将对象作为“键”,如果您需要来自对象的信息,请按此方式设置,否则使用您需要的特定属性作为键。(ID、CODE 等。如在 plcckr 示例中)
  4. 设置下拉/选择控件值的方式取决于#3,

    • 如果下拉键是单个属性(就像 plunkr 中的所有示例一样),您只需设置它,例如: $scope.dropdownmodel = $scope.user.state;
    • 如果将对象设置为键,则需要通过选项循环,即使分配对象也不会将项目设置为选中,因为它们将具有不同的哈希键,例如:

      for (var i = 0, len = $scope.options.length; i < len; i++) {
        if ($scope.options[i].id == savedValue) { // Your own property here:
          console.log('Found target! ');
          $scope.value = $scope.options[i];
          break;
        }
      }
      

您可以替换另一个对象中相同属性的 savedValue,$scope.myObject.myProperty

于 2014-03-11T09:50:39.763 回答
3

对我来说,布鲁诺戈麦斯的答案是最好的答案。

但实际上,您不必担心设置选择选项的 value 属性。AngularJS 会解决这个问题。让我详细解释一下。

请考虑这个小提琴

angular.module('mySettings', []).controller('appSettingsCtrl', function ($scope) {

    $scope.timeFormatTemplates = [{
        label: "Seconds",
        value: 'ss'
    }, {
        label: "Minutes",
        value: 'mm'
    }, {
        label: "Hours",
        value: 'hh'
    }];


    $scope.inactivity_settings = {
        status: false,
        inactive_time: 60 * 5 * 3, // 15 min (default value), that is, 900 seconds
        //time_format: 'ss', // Second (default value)
        time_format: $scope.timeFormatTemplates[0], // Default seconds object
    };

    $scope.activity_settings = {
        status: false,
        active_time: 60 * 5 * 3, // 15 min (default value), that is,  900 seconds
        //time_format: 'ss', // Second (default value)
        time_format: $scope.timeFormatTemplates[0], // Default seconds object
    };

    $scope.changedTimeFormat = function (time_format) {
        'use strict';

        console.log('time changed');
        console.log(time_format);
        var newValue = time_format.value;

        // do your update settings stuffs
    }
});

正如您在小提琴输出中看到的那样,无论您为选择框选项选择什么,它都是您的自定义值,或者 AngularJS 自动生成的 0、1、2 值,除非您使用 jQuery 或任何其他库来访问该选择组合框选项的值并相应地对其进行操作。

于 2015-03-12T09:12:23.563 回答
3

请使用在选择框中区分值和标签的属性跟踪。

请试试

<select ng-options="obj.text for obj in array track by obj.value"></select>

这将分配带有文本的标签和带有值的值(来自数组)

于 2017-05-09T11:00:43.970 回答
2

对于一个对象:

<select ng-model="mySelect" ng-options="key as value for (key, value) in object"></select>
于 2013-10-31T08:45:47.037 回答
2

对于开发人员来说,使用 ng-options 总是很痛苦。例如:在选择标签中获取一个空/空白的选定值。尤其是在 ng-options 中处理 JSON 对象时,变得更加乏味。在这里,我做了一些练习。

目标:通过 ng-option 迭代 JSON 对象数组并设置选定的第一个元素。

数据:

someNames = [{"id":"1", "someName":"xyz"}, {"id":"2", "someName":"abc"}]

在选择标签中,我必须显示 xyz 和 abc,其中 xyz 必须毫不费力地选择。

HTML:

<pre class="default prettyprint prettyprinted" style=""><code>
    &lt;select class="form-control" name="test" style="width:160px"    ng-options="name.someName for name in someNames" ng-model="testModel.test" ng-selected = "testModel.test = testModel.test || someNames[0]"&gt;
&lt;/select&gt;
</code></pre>

通过上面的代码示例,您可能会摆脱这种夸张。

另一个参考

于 2014-07-28T11:29:29.077 回答
2

教程ANGULAR.JS: NG-SELECT AND NG-OPTIONS帮助我解决了这个问题:

<select id="countryId"
  class="form-control"
  data-ng-model="entity.countryId"
  ng-options="value.dataValue as value.dataText group by value.group for value in countries"></select>
于 2014-08-31T23:16:36.893 回答
1
<select ng-model="output">
   <option ng-repeat="(key,val) in dictionary" value="{{key}}">{{val}}</option>
</select>
于 2015-04-18T02:15:55.217 回答
1

运行代码片段并查看变化。这是快速理解的注释

  1. 示例 1(对象选择):- ng-option="os.name for os in osList track by os.id"。这里track by os.id很重要 &应该在那里,之前os.id as 不应该os.name有。

    • 应该设置为ng-model="my_os"键为id的对象my_os={id: 2}
  2. 示例 2(值选择):- ng-option="os.id as os.name for os in osList"。这里track by os.id 不应该在那里,os.id as 应该在之前os.name

    • ng-model="my_os"应该设置为一个值,如my_os= 2

其余代码片段将解释。

angular.module('app', []).controller('ctrl', function($scope, $timeout){
  
  //************ EXAMPLE 1 *******************
  $scope.osList =[
    { id: 1, name :'iOS'},
    { id: 2, name :'Android'},
    { id: 3, name :'Windows'}
  ]
  $scope.my_os = {id: 2};
  
  
  //************ EXAMPLE 2 *******************
  $timeout(function(){
    $scope.siteList = [
          { id: 1, name: 'Google'},
          { id: 2, name: 'Yahoo'},
          { id: 3, name: 'Bing'}
        ];
   }, 1000);
    
    $scope.my_site = 2;
  
    $timeout(function(){
      $scope.my_site = 3;
    }, 2000);
})
fieldset{
  margin-bottom: 40px;
  }
strong{
  color:red;
  }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.10/angular.min.js"></script>

<div ng-app="app" ng-controller="ctrl">

  <!--//************ EXAMPLE 1 *******************-->
  <fieldset>
    <legend>Example 1 (Set selection as <strong>object</strong>)</legend>
    
    <select ng-model="my_os" ng-options="os.name for os in osList track by os.id">
        <option value="">--Select--</option>
      </select>
    {{my_os}}
    
  </fieldset>
  
  
  <!--//************ EXAMPLE 2 *******************-->
  <fieldset>
    <legend>Example 2 (Set selection as <strong>value</strong>. Simulate ajax)</legend>
      <select ng-model="my_site" ng-options="site.id as site.name for site in siteList">
        <option value="">--Select--</option>
      </select>
      {{my_site}}
  </fieldset>
  
</div>

于 2017-01-12T07:03:19.510 回答
0

就像许多人之前所说的,如果我有这样的数据:

countries : [
              {
                 "key": 1,
                 "name": "UAE"
             },
              {
                  "key": 2,
                  "name": "India"
              },
              {
                  "key": 3,
                  "name": "OMAN"
              }
         ]

我会像这样使用它:

<select
    ng-model="selectedCountry"
    ng-options="obj.name for obj  in countries">
</select>

在您的控制器中,您需要设置一个初始值以摆脱第一个空项:

 $scope.selectedCountry = $scope.countries[0];

 // You need to watch changes to get selected value
 $scope.$watchCollection(function() {
   return $scope.selectedCountry
 }, function(newVal, oldVal) {
     if (newVal === oldVal) {
       console.log("nothing has changed " + $scope.selectedCountry)
     } 
     else {
       console.log('new value ' + $scope.selectedCountry)
     }
 }, true)
于 2015-03-15T11:51:54.623 回答
0

以下是我在遗留应用程序中解决此问题的方法:

在 HTML 中:

ng-options="kitType.name for kitType in vm.kitTypes track by kitType.id" ng-model="vm.itemTypeId"

在 JavaScript 中:

vm.kitTypes = [
    {"id": "1", "name": "Virtual"},
    {"id": "2", "name": "Physical"},
    {"id": "3", "name": "Hybrid"}
];

...

vm.itemTypeId = vm.kitTypes.filter(function(value, index, array){
    return value.id === (vm.itemTypeId || 1);
})[0];

我的 HTML 正确显示了选项值。

于 2015-03-17T07:26:59.877 回答
0

ngOptions 指令:

$scope.items = [{name: 'a', age: 20},{ name: 'b', age: 30},{ name: 'c', age: 40}];
  • Case-1) 数组中值的标签:

    <div>
        <p>selected item is : {{selectedItem}}</p>
        <p> age of selected item is : {{selectedItem.age}} </p>
        <select ng-model="selectedItem" ng-options="item.name for item in items">
        </select>
    </div>
    

输出说明(假设选择了第一个项目):

selectedItem = {name: 'a', age: 20} // [默认情况下,选中项等于值]

selectedItem.age = 20

  • 案例 2)选择作为数组中值的标签:

    <div>
        <p>selected item is : {{selectedItem}}</p>
        <select ng-model="selectedItem" ng-options="item.age as item.name for item in items">
        </select>
    </div>
    

输出说明(假设第一个项目被选中): selectedItem = 20 // [选择部分是item.age ]

于 2017-10-14T14:24:09.950 回答