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
How do I set the value property in AngularJS' ng-options?
提问by Jukka Puranen
Here is what seems to be bothering a lot of people (including me).
这似乎困扰着很多人(包括我)。
When using the ng-options
directive 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 resultOptions
is 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 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
For object data sources: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
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
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 value
attribute of select
element with track by
expression.
随着 AngularJS 的更新,现在可以使用表达式设置元素value
属性的实际值。select
track 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.id
in the code, but we don't want to show the id
to the user; we want to show its name. Likewise, we're not interested in the person.name
in the code. There comes the as
keyword 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.id
we could need the person
instance/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 option
elements 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_hero
to 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 iron
or super
as the value of my_hero
.
服务器将接收iron
或super
作为 的值my_hero
。
This is similar to the answer by @neemzy, but specifying separate data for the value
attribute.
这类似于@neemzy 的答案,但为value
属性指定了单独的数据。
回答by Joshcodes
It appears that ng-options
is 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-options
provides thefor
keyword 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-options
provides theas
keyword to specify what value is provided to the model as ink 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 <li />
's under <ul />
's and place a ng-repeat on an option element:
如果 MVC HTML 页面对于手头的问题是不必要的过度设计:那么仅使用 AngularJS 的 (V) 视图组件的 HTML 生成部分。在这种情况下,请遵循用于生成元素(例如<li />
's under <ul />
'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 by
the 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-options
to 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 将是显示给用户的文本选项。我认为“跟踪”是混乱和矫枉过正的。