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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12139152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:12:05  来源:igfitidea点击:

How do I set the value property in AngularJS' ng-options?

javascriptangularjs

提问by Jukka Puranen

Here is what seems to be bothering a lot of people (including me).

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

When using the ng-optionsdirective in AngularJS to fill in the options for a <select>tag, I cannot figure out how to set the value for an option. The documentation for this is really unclear - at least for a simpleton like me.

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

I can set the text for an option easily like so:

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

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

When resultOptionsis for example:

resultOptions例如为:

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

It should be (and probably is) the most simple thing to set the option values, but so far I just don't get it.

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

回答by Umur Kontac?

See ngOptions

ngOptions(optional)– {comprehension_expression=} – in one of the following forms:

For array data sources: label for value in arrayselect as label for value in arraylabel group by group for value in arrayselect as label group by group for value in array track by trackexprFor object data sources:label for (key , value) in objectselect as label for (key , value) in objectlabel group by group for (key, value) in objectselect as label group by group for (key, value) in object

查看ngOptions

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

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

In your case, it should be

在你的情况下,它应该是

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

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

Update

更新

With the updates on AngularJS, it is now possible to set the actual value for the valueattribute of selectelement with track byexpression.

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

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

How to remember this ugly stuff

如何记住这些丑陋的东西

To all the people who are having hard time to remember this syntax form: I agree this isn't the most easiest or beautiful syntax. This syntax is kind of an extended version of Python's list comprehensions and knowing that helps me to remember the syntax very easily. It's something like this:

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

Python code:

蟒蛇代码:

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

This is actually the same syntax as the first one listed above. However, in <select>we usually need to differentiate between the actual value in code and the text shown (the label) in a <select>element.

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

Like, we need person.idin the code, but we don't want to show the idto the user; we want to show its name. Likewise, we're not interested in the person.namein the code. There comes the askeyword to label stuff. So it becomes like this:

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

person.id as person.name for person in people

Or, instead of person.idwe could need the personinstance/reference itself. See below:

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

person as person.name for person in people

For JavaScript objects, the same method applies as well. Just remember that the items in the object is deconstructed with (key, value)pairs.

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

回答by frm.adiputra

How the value attributes gets its value:

值属性如何获取其值:

  • When using an array as datasource, it will be the index of the array element in each iteration;
  • When using an object as datasource, it will be the property name in each iteration.
  • 使用数组作为数据源时,每次迭代时为数组元素的索引;
  • 当使用对象作为数据源时,它将是每次迭代中的属性名称。

So in your case it should be:

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

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

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

回答by Bruno Gomes

I had this issue too. I wasn't able to set my value in ng-options. Every option that was generated was set with 0, 1, ..., n.

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

To make it right, I did something like this in my ng-options:

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

HTML:

HTML:

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

I use "track by" to set all my values with room.price.

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

(This example sucks: because if there were more than one price equal, the code would fail. So BE SURE to have different values.)

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

JSON:

JSON:

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

I learned it from blog post How to set the initial selected value of a select element using Angular.JS ng-options & track by.

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

Watch the video. It's a nice class :)

观看视频。这是一堂不错的课:)

回答by neemzy

If you want to change the value of your optionelements because the form will eventually be submitted to the server, instead of doing this,

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

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

You can do this:

你可以这样做:

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

The expected value will then be sent through the form under the correct name.

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

回答by Philip Bulley

To send a custom value called my_heroto the server using a normal form submit:

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

JSON:

JSON:

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

HTML:

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}}" />

The server will receive either ironor superas the value of my_hero.

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

This is similar to the answer by @neemzy, but specifying separate data for the valueattribute.

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

回答by Joshcodes

It appears that ng-optionsis complicated (possibly frustrating) to use, but in reality we have an architecture problem.

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

AngularJS serves as an MVC framework for a dynamic HTML+JavaScript application. While its (V)iew component does offer HTML "templating," its primary purpose is to connect user actions, via a controller, to changes in the model. Therefore the appropriate level of abstraction, from which to work in AngularJS, is that a select element sets a value in the model to a value from a query.

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

  • How a query row is presented to the user is the (V)iew's concern and ng-optionsprovides the forkeyword to dictate what the contents of the option element should be i.e.p.text for p in resultOptions.
  • How a selected row is presented to the server is the (M)odel's concern. Therefore ng-optionsprovides the askeyword to specify what value is provided to the model as in k as v for (k,v) in objects.
  • 查询行如何呈现给用户是 (V) 视图的关注点,并ng-options提供for关键字来指示选项元素的内容应该是iep.text for p in resultOptions
  • 选定的行如何呈现给服务器是 (M) 模型所关心的。因此ng-options提供as关键字来指定提供给模型的值,如k as v for (k,v) in objects

The correct solution this is problem is then architectural in nature and involves refactoring your HTML so that the (M)odel performs server communication when required(instead of the user submitting a form).

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

If an MVC HTML page is unnecessary over-engineering for the problem at hand:then use only the HTML generation portion of AngularJS's (V)iew component. In this case, follow the same pattern that is used for generating elements such as &lt;li /&gt;'s under &lt;ul /&gt;'s and place a ng-repeat on an option element:

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

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

As kludge, one can always move the name attribute of the select element to a hidden input element:

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

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

回答by Liko

You can do this:

你可以这样做:

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

-- UPDATE

- 更新

After some updates, user frm.adiputra's solutionis much better. Code:

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

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

回答by Jeffrey A. Gochin

I have struggled with this problem for a while today. I read through the AngularJS documentation, this and other posts and a few of blogs they lead to. They all helped me grock the finer details, but in the end this just seems to be a confusing topic. Mainly because of the many syntactical nuances of ng-options.

今天我一直在与这个问题作斗争。我通读了 AngularJS 文档、这篇文章和其他文章以及它们指向的一些博客。他们都帮助我掌握了更精细的细节,但最终这似乎是一个令人困惑的话题。主要是因为ng-options.

In the end, for me, it came down to less is more.

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

Given a scope configured as follows:

给定一个范围配置如下:

        //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
        };

This is all I needed to get the desired result:

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

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

Notice I did not use track by. Using track bythe selected item would alway return the object that matched the FirmnessID, rather than the FirmnessID itself. This now meets my criteria, which is that it should return a numeric value rather than the object, and to use ng-optionsto gain the performance improvement it provides by not creating a new scope for each option generated.

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

Also, I needed the blank first row, so I simply added an <option>to the <select>element.

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

Here is a Plunkrthat shows my work.

这是一个展示我工作的Plunkr

回答by blue

This was best suited for all scenarios according to me:

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

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

where you can use your model to bind the data. You will get the value as the object will contain and the default selection based on your scenario.

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

回答by KthProg

Instead of using the new 'track by' feature you can simply do this with an array if you want the values to be the same as the text:

如果您希望值与文本相同,则无需使用新的 'track by' 功能,您可以简单地使用数组执行此操作:

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

Note the difference between the standard syntax, which will make the values the keys of the Object/Array, and therefore 0,1,2 etc. for an array:

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

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

k as vbecomes v as v.

k as v变成v as v

I discovered this just based on common sense looking at the syntax. (k,v) is the actual statement that splits the array/object into key value pairs.

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

In the 'k as v' statement, k will be the value, and v will be the text option displayed to the user. I think 'track by' is messy and overkill.

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