以下是困扰很多人(包括我)的问题。
当在AngularJS中使用ng-options指令来填充<select>标记的选项时,我不知道如何为一个选项设置值。这方面的文档确实不清楚——至少对我这样的傻瓜来说是这样。
我可以像这样轻松地设置一个选项的文本:
ng-options="select p.text for p in resultOptions"
例如,当resultOptions为:
[
{
"value": 1,
"text": "1st"
},
{
"value": 2,
"text": "2nd"
}
]
它应该是(可能是)设置选项值最简单的事情,但到目前为止,我只是不明白它。
这就是我解决这个问题的方法。我根据值跟踪了选择,并在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是我的控制器,从服务检索到的控制器中的国家是{CountryId =1, Code =' USA', CountryName='United States of America'}。
当我从选择下拉菜单中选择了另一个国家,并发布了“保存”页面时,我得到了正确的国家边界。
今天我已经为这个问题纠结了一段时间。我通读了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。使用所选项的跟踪将总是返回与FirmnessID匹配的对象,而不是FirmnessID本身。这现在满足了我的标准,即它应该返回一个数值而不是对象,并且使用ng-options来获得它所提供的性能改进,而不是为生成的每个选项创建一个新的作用域。
同样,我需要空白的第一行,所以我简单地在<select>元素中添加了一个<option>。
这是一个展示我作品的Plunkr。
ng-options看起来使用起来很复杂(可能令人沮丧),但实际上我们有一个架构问题。
AngularJS是动态HTML+JavaScript应用程序的MVC框架。虽然它的(V)视图组件确实提供了HTML“模板”,但它的主要目的是通过控制器将用户操作连接到模型中的更改。因此,在AngularJS中,适当的抽象级别是select元素将模型中的值设置为来自查询的值。
查询行如何呈现给用户是(V)视图关心的问题,ng-options提供了for关键字来指示选项元素的内容应该是什么,即p.text for resultOptions中的p。
所选的行如何呈现给服务器是(M)模型所关心的。因此ng-options提供了as关键字来指定在对象中(k,v)的k和v中向模型提供什么值。
这个问题的正确解决方案是本质上的体系结构,并涉及重构HTML,以便(M)模型在需要时执行服务器通信(而不是用户提交表单)。
如果一个MVC HTML页面对于手头的问题来说是不必要的过度工程:那么只使用AngularJS的(V)视图组件的HTML生成部分。在这种情况下,遵循与生成<ul />'s下的<li />'s相同的模式,并在一个选项元素上放置ng-repeat:
<select name=“value”>
<option ng-repeat=“value in Model.Values” value=“{{value.value}}”>
{{value.text}}
</option>
</select>
作为临时拼凑,我们总是可以将选择元素的name属性移动到一个隐藏的输入元素:
<select ng-model=“selectedValue” ng-options=“value.text for value in Model.Values”>
</select>
<input type=“hidden” name=“value” value=“{{selectedValue}}” />
就像很多人之前说的,如果我有这样的数据:
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)