这似乎困扰着很多人(包括我)。
在 AngularJS 中使用 ng-options
指令填充 <select>
标记的选项时,我无法弄清楚如何设置选项的值。这方面的文档真的不清楚 - 至少对于像我这样的傻瓜来说。
我可以像这样轻松地为选项设置文本:
ng-options="select p.text for p in resultOptions"
例如,当 resultOptions
是:
[
{
"value": 1,
"text": "1st"
},
{
"value": 2,
"text": "2nd"
}
]
设置选项值应该是(并且可能是)最简单的事情,但到目前为止我还是不明白。
请参阅 ngOptions ngOptions(optional) – {comprehension_expression=} – 采用以下形式之一: 对于数组数据源:数组中值的标签 选择作为数组中值的标签 标签组按组为数组中的值选择标签组对于数组中的值 track by trackexpr 对于对象数据源: 对象中的 (key , value) 的标签 select as label for (key , value) in object label group by group for (key, value) 对象中的标签 按组选择对象中的(键,值)
在你的情况下,它应该是
array = [{ "value": 1, "text": "1st" }, { "value": 2, "text": "2nd" }];
<select ng-options="obj.value as obj.text for obj in array"></select>
更新
随着 AngularJS 的更新,现在可以使用 track by
表达式为 select
元素的 value
属性设置实际值。
<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
实例/引用本身,而不是 person.id
。见下文:
person as person.name for person in people
对于 JavaScript 对象,同样的方法也适用。请记住,对象中的项目是用 (key, value)
对解构的。
值属性如何获取其值:
使用数组作为数据源时,每次迭代都会是数组元素的索引;
当使用对象作为数据源时,它将是每次迭代中的属性名称。
所以在你的情况下应该是:
obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>
我也有这个问题。我无法在 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。
观看视频。这是一堂很好的课:)
如果您想更改 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 }}" />
然后将通过正确名称的表单发送预期值。
<input type="hidden" name="text" value="{{ text }}" />
,我会使用 ng-value
。所以:<input type="hidden" name="text" ng-value="{{ text }}" />
。
要使用普通表单提交将名为 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}}" />
服务器将接收 iron
或 super
作为 my_hero
的值。
这类似于 the answer by @neemzy,但为 value
属性指定单独的数据。
看起来 ng-options
使用起来很复杂(可能令人沮丧),但实际上我们遇到了架构问题。
AngularJS 用作动态 HTML+JavaScript 应用程序的 MVC 框架。虽然它的 (V)iew 组件确实提供了 HTML“模板”,但它的主要目的是通过控制器将用户操作连接到模型中的更改。因此,在 AngularJS 中工作的适当抽象级别是选择元素将模型中的值设置为查询中的值。
查询行如何呈现给用户是 (V)iew 的关注点,ng-options 提供了 for 关键字来指示 option 元素的内容应该是 resultOptions 中 p 的 ieptext。
如何将选定的行呈现给服务器是 (M) 模型的关注点。因此 ng-options 提供了 as 关键字来指定为模型提供什么值,如在对象中的 (k,v) 中的 k 和 v。
这个问题的正确解决方案本质上是架构性的,并且涉及重构您的 HTML,以便 (M) 模型在需要时执行服务器通信(而不是用户提交表单)。
如果一个 MVC HTML 页面对于手头的问题是不必要的过度设计:那么只使用 AngularJS 的 (V)iew 组件的 HTML 生成部分。在这种情况下,请遵循用于在 <ul />
下生成 <li />
等元素的相同模式,并在选项元素上放置 ng-repeat:
<select name=“value”>
<option ng-repeat=“value in Model.Values” value=“{{value.value}}”>
{{value.text}}
</option>
</select>
如 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}}” />
"Note: ngOptions provides an iterator facility for the <option> element which should be used instead of ngRepeat when you want the select model to be bound to a non-string value. This is because an option element can only be bound to string values at present."
。没有提到性能,只是说 ngOptions 是 ngRepeat 的替代品。
你可以这样做:
<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>
我今天已经为这个问题苦苦挣扎了一段时间。我通读了 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
通过不为生成的每个选项创建新范围来获得它提供的性能改进。
此外,我需要空白的第一行,所以我只是在 <select>
元素中添加了一个 <option>
。
这是显示我的工作的 Plunkr。
如果您希望值与文本相同,则无需使用新的“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 是显示给用户的文本选项。我认为“跟踪”是混乱和矫枉过正。
根据我的说法,这最适合所有场景:
<select ng-model="mySelection.value">
<option ng-repeat="r in myList" value="{{r.Id}}" ng-selected="mySelection.value == r.Id">{{r.Name}}
</option>
</select>
您可以在其中使用模型来绑定数据。您将获得对象将包含的值以及基于您的方案的默认选择。
这就是我解决这个问题的方法。我跟踪了按值选择,并在我的 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'}
。
当我从选择下拉列表中选择另一个国家并使用“保存”发布我的页面时,我得到了正确的国家绑定。
ng-options
指令未在数组的 <options>
元素上设置 value 属性:
使用 limit.value as limit.text for limit in limits
意味着:
将
请参阅 Stack 溢出问题 AngularJS ng-options not rendering values。
可以使用 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>
效果很好
<select ng-model="color" ng-options="(c.name+' '+c.shade) for c in colors"></select><br>
提出问题一年后,我不得不为这个问题找到答案,因为至少对我来说,这些都没有给出实际答案。
您已经问过如何选择该选项,但没有人说这两件事不一样:
如果我们有这样的选择:
$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/。
这个问题的正确答案是 provided by user frm.adiputra,因为目前这似乎是显式控制选项元素的 value 属性的唯一方法。
但是,我只是想强调一下,“select”在这种情况下不是关键字,而只是表达式的占位符。请参考以下列表,了解“select”表达式的定义以及可以在 ng-options 指令中使用的其他表达式。
问题中描述的 select 的使用:
ng-options='select p.text for p in resultOptions'
本质上是错误的。
根据表达式列表,当在对象数组中给出选项时,似乎 trackexpr 可用于指定值,但它仅用于分组。
来自 AngularJS 的 ng-options 文档:
数组/对象:计算结果为要迭代的数组/对象的表达式。
value:局部变量,将在迭代期间引用数组中的每个项目或对象的每个属性值。
key:局部变量,在迭代期间将引用对象中的属性名称。
标签:此表达式的结果将是元素的标签。表达式很可能引用值变量(例如 value.propertyName)。
select:此表达式的结果将绑定到父元素的模型。如果未指定,则选择表达式将默认为值。
group:此表达式的结果将用于使用 DOM 元素对选项进行分组。
trackexpr:在处理对象数组时使用。此表达式的结果将用于识别数组中的对象。 trackexpr 很可能会引用 value 变量(例如 value.propertyName)。
根据您设置数据源的方式,在 ng-options 中选择一个项目可能会有些棘手。
在与他们斗争了一段时间后,我最终用我使用的最常见的数据源制作了一个样本。你可以在这里找到它:
http://plnkr.co/edit/fGq2PM?p=preview
现在要使 ng-options 工作,这里有一些事情需要考虑:
通常,您从一个来源获得选项,从另一个来源获得选定的值。例如:states :: data for ng-options user.state :: 选项设置为选中 基于 1,最简单/合乎逻辑的做法是用一个源填充选择,然后通过代码设置所选值。获得混合数据集很少会更好。 AngularJS 允许选择控件持有多个键 |标签。许多在线示例将对象作为“键”,如果您需要来自对象的信息,请按此方式设置,否则使用您需要的特定属性作为键。 (ID、CODE 等。如在 plckr 示例中)设置下拉/选择控件值的方式取决于 #3,如果下拉键是单个属性(如 plunkr 中的所有示例),您只需设置它,例如:$scope.dropdownmodel = $scope.user.state;如果将对象设置为键,则需要循环通过选项,即使分配对象也不会将项目设置为选中,因为它们将具有不同的哈希键,例如:for (var i = 0, len = $scope.options. length; i < len; i++) { if ($scope.options[i].id == savedValue) { // 这里是你自己的属性:console.log('Found target!'); $scope.value = $scope.options[i];休息; } }
您可以替换另一个对象 $scope.myObject.myProperty
中相同属性的 savedValue。
对我来说the answer by Bruno Gomes是最好的答案。
但实际上,您不必担心设置选择选项的 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 或任何其他库来访问该选择组合框选项的值并相应地对其进行操作。
请使用在选择框中区分值和标签的属性跟踪。
请试试
<select ng-options="obj.text for obj in array track by obj.value"></select>
这将分配带有文本的标签和带有值的值(来自数组)
对于一个对象:
<select ng-model="mySelect" ng-options="key as value for (key, value) in object"></select>
对于开发人员来说,使用 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>
<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]">
</select>
</code></pre>
通过上面的代码示例,您可能会摆脱这种夸张。
另一个reference:
教程 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>
<select ng-model="output">
<option ng-repeat="(key,val) in dictionary" value="{{key}}">{{val}}</option>
</select>
运行代码片段并查看变化。这是快速理解的注释
示例 1(对象选择):- ng-option="os.name for os in osList track by os.id"。这里通过 os.id 进行跟踪很重要,应该存在,并且 os.id 在 os.name 之前不应该有。 ng-model="my_os" 应该设置为一个对象,其键为 id,如 my_os={id: 2}。示例 2(值选择):- ng-option="os.id as os.name for os in osList"。这里不应该有 os.id 的跟踪,而 os.id 应该在 os.name 之前。 ng-model="my_os" 应该设置为类似 my_os= 2 的值
其余代码片段将解释。
angular.module('app', []).controller('ctrl', function($scope, $timeout){ //************ 示例 1 ******* ************ $scope.osList =[ { id: 1, name :'iOS'}, { id: 2, name :'Android'}, { id: 3, name :' Windows'} ] $scope.my_os = {id: 2}; //************ 示例 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; } 强{ 颜色:红色; }
就像许多人之前所说的,如果我有这样的数据:
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)
以下是我在遗留应用程序中解决此问题的方法:
在 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 正确显示了选项值。
ngOptions 指令:
$scope.items = [{name: 'a', age: 20},{ name: 'b', age: 30},{ name: 'c', age: 40}];
Case-1) 数组中值的标签:
所选项目为:{{selectedItem}}
所选项目的年龄为:{{selectedItem.age}}
< select ng-model="selectedItem" ng-options="item.name for item in items">输出说明(假设选择了第一个项目):
selectedItem = {name: 'a', age: 20} // [默认情况下,选中项等于值项]
selectedItem.age = 20
案例2)选择作为数组中值的标签:
所选项目是:{{selectedItem}}
输出说明(假设第一个项目被选中): selectedItem = 20 // [选择部分是 item.age]