如何在AngularJS的ng-options中设置value属性?

时间:2012-08-27 09:13:25

标签: javascript angularjs

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

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

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

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

resultOptions为例:

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

设置选项值应该是(也可能是)最简单的事情,但到目前为止我还是没有得到它。

27 个答案:

答案 0 :(得分:681)

  

请参阅 ngOptions

     

ngOptions(可选) - {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表达式设置select元素的track 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)对解构的。

答案 1 :(得分:133)

值属性如何获得其值:

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

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

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

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

答案 2 :(得分:118)

我也有这个问题。我无法在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>

我使用&#34;跟踪&#34;用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 中学到的。

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

答案 3 :(得分:46)

如果您想更改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 }}" />

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

答案 4 :(得分:25)

使用普通表单提交将名为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的值。

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

答案 5 :(得分:23)

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

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

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

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

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

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

作为kludge,可以随时将select元素的name属性移动到隐藏的输入元素:

<select ng-model=“selectedValue” ng-options=“value.text for value in Model.Values”>
</select>
<input type=“hidden” name=“value” value=“{{selectedValue}}” />

答案 6 :(得分:19)

你可以这样做:

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

- 更新

经过一些更新后,user frm.adiputra's solution要好得多。代码:

obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>

答案 7 :(得分:13)

今天我一直在努力解决这个问题。我通读了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

答案 8 :(得分:10)

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

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

您可以使用模型绑定数据。您将获得对象将包含的值以及基于您的场景的默认选择。

答案 9 :(得分:10)

如果您希望值与文本相同,则可以使用数组执行此操作,而不是使用新的“跟踪依据”功能:

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

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

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

k,因为v 变为 v as v

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

在'k as v'语句中,k将是值,v将是显示给用户的文本选项。我认为“追踪”是一种混乱和过度杀伤。

答案 10 :(得分:8)

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

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是我的控制器,从服务中检索到的控制器中的国家/地区为{CountryId =1, Code = 'USA', CountryName='United States of America'}

当我从选择下拉列表中选择了另一个国家/地区并使用&#34; Save&#34;发布了我的页面时,我得到了正确的国家/地区。

答案 11 :(得分:7)

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

答案 12 :(得分:4)

<select ng-model="color" ng-options="(c.name+' '+c.shade) for c in colors"></select><br>

答案 13 :(得分:3)

您可以使用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>

效果很好

答案 14 :(得分:3)

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

请尝试

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

将为文本和值赋值标签(来自数组)

答案 15 :(得分:3)

对我来说the answer by Bruno Gomes是最好的答案。

但实际上,您无需担心设置select选项的value属性。 AngularJS将负责这一点。让我详细解释一下。

Please consider this fiddle

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或任何其他库来访问该选择组合框选项的值并相应地操作它。

答案 16 :(得分:3)

问题发生一年后,我必须找到这个问题的答案,因为其中没有给出实际答案,至少对我来说。

您已经询问如何选择该选项,但没有人说这两件事情相同:

如果我们有这样的选项:

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

我们尝试设置一个默认选项:

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

NOT 工作,但如果您尝试选择这样的选项:

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

工作

即使这两个对象具有相同的属性,AngularJS也将它们视为不同,因为AngularJS会比较引用

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

答案 17 :(得分:3)

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

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

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

现在要使ng-options工作,需要考虑以下事项:

  1. 通常,您可以从一个来源获取选项,从另一个来源获取所选值。例如:
    • states :: ng-options的数据
    • user.state ::选项设置为选中
  2. 基于1,最简单/逻辑的做法是用一个源填充选择,然后通过代码设置选定的值。获得混合数据集很少会更好。
  3. AngularJS允许选择控件保持超过key | label。许多在线示例将对象设置为“键”,如果您需要来自对象的信息,请将其设置为关键,否则请使用您需要的特定属性作为键。 (ID,CODE等。如plckr样本中那样)
  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;
        }
      }
      
  5. 您可以将savedValue替换为另一个对象$scope.myObject.myProperty中的相同属性。

答案 18 :(得分:3)

这个问题的正确答案是provided by user frm.adiputra,因为目前这似乎是明确控制选项元素的value属性的唯一方法。

但是,我只想强调“select”在这个上下文中不是关键字,但它只是表达式的占位符。有关“select”表达式的定义以及可在ng-options指令中使用的其他表达式,请参阅以下列表。

在问题中描述了select的使用:

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

本质上是错误的。

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


来自AngularJS的ng-options文档:

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

答案 19 :(得分: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>

答案 20 :(得分:2)

开发人员使用ng-options总是很痛苦。例如:在select标记中获取空/空选定值。特别是在处理ng-options中的JSON对象时,它变得更加乏味。在这里,我做了一些练习。

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

数据:

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

在select标签中我必须显示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>

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

另一个reference

答案 21 :(得分:2)

对象:

<select ng-model="mySelect" ng-options="key as value for (key, value) in object"></select>

答案 22 :(得分:1)

<select ng-model="output">
   <option ng-repeat="(key,val) in dictionary" value="{{key}}">{{val}}</option>
</select>

答案 23 :(得分:1)

运行代码段并查看变体。以下是快速理解的说明

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

    • os.name应设置为键为 id 的对象,如ng-model="my_os"
  2. 示例2(值选择): - my_os={id: 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"
    • 之类的值
  3. Rest代码片段将解释。

    &#13;
    &#13;
    my_os= 2
    &#13;
    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);
    })
    &#13;
    fieldset{
      margin-bottom: 40px;
      }
    strong{
      color:red;
      }
    &#13;
    &#13;
    &#13;

答案 24 :(得分: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)

答案 25 :(得分: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正确显示选项值。

答案 26 :(得分:0)

ngOptions指令:

(30000,1000) = X.shape
(1000,1) = b.shape
(1000,1) = a.shape
  • 案例1)数组中值的标签:

    $scope.items = [{name: 'a', age: 20},{ name: 'b', age: 30},{ name: 'c', age: 40}];
    

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

selectedItem = {name:&#39; a&#39;,age:20} // [默认情况下,所选项目等于值 item

selectedItem.age = 20

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

    <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>
    

输出说明(假设选择了第1项): selectedItem = 20 // [选择部分 item.age ]