源:http://www.undefinednull.com/2014/08/11/a-brief-walk-through-of-the-ng-options-in-angularjs
在使用ng-options经常会遇到一些困难。在实际使用中经常会搞的自己焦头烂额。因此在大部分时间,不得不使用google查询它的工作原理。Angularjs官方文档中只有较少的说明和示例。但是,通过查看Stackoverflow中的描述使我理解了这个概念,决定写下这个博客。显然,这对我来说很有用,至少不用每次在使用的时候去google了,嘿嘿。
为什么使用 ng-options ?
首先,先了解下ng-repeat。在Angularjs创建菜单最简单的方法是使用ng-repeat,看下面的代码:
Html
<html ng-app="app">
<body>
<div ng-controller="Test">
<p>selected item is : {{selectedItem}}</p>
<select ng-model="selectedItem">
<option ng-repeat="item in items" value="{{item}}">{{item}}</option>
</select>
</div>
</body>
</html>
JavaScript
var app = angular.module('app',[]);
app.controller('Test',function($scope){
$scope.items = ['one','two','three','four']
});
上面的代码中,在属性中存在一个名为
items
的文本数组,而且在理想状态下,它的所有项均为字符串。(译者注,实际中更多为json对象数组)上述方法,在数组中包含对象时无法使用。
Angularjs的官方文档中指出,在上述情况中,对于‘select’应使用ng-options代替ng-repeat。其原因为,option元素只能使用string类型的数据作为其value值。
从Angularjs官方文档的引用:
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.
将items变为对象数组
JavaScript
$scope.items = [{name: 'one', age: 30 },{ name: 'two', age: 27 },{ name: 'three', age: 50 }];
Html
<html ng-app="app">
<body>
<div ng-controller="Test">
<p>selected item is : {{selectedItem}}</p>
<select ng-model="selectedItem">
<option ng-repeat="item in items" value="{{item.age}}">{{item.name}}</option>
</select>
</div>
</body>
</html>
如果仔细观察,会发现模型 selectedItem
与被选中的option元素相绑定。这里就像之前解释过的,我们被限制只能在items数组中使用string类型。因而无法将items中的对象赋值给 selectedItem。因此对于此类情况,我们就需要使用ng-options。下面,让我们来看如何去做。
使用ng-options重写上述代码:
<html ng-app="app">
<body>
<div ng-controller="Test">
<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>
</body>
</html>
现在
selectedItem
被绑定到一个对象上,而不是string类型的值。可以通过这里查看
$scope.selectedItem = $scope.items[0];
将selectedItem的值设置为items数组中的第一个对象,来修复这个问题。
不同的语法
对于数组类型数据
label
for value
in array
label
产生在每个option元素中的文本,所以在数组中包含所有基本元素时,它应该和 value
的名字相同,在上面的例子中,label和value的名字都为 item
。
$scope.items = [{name: 'one', age: 30 },{ name: 'two', age: 27 },{ name: 'three', age: 50 }];
同时改变表达式为
ng-options="item.name for item in items"
上面的代码和容易理解。我们告诉angularjs去遍历items数组,并且使用
item.name
作为option元素的文本。现在让我们查看一些更为复杂的表达式。
select
as label
for value
in array
在默认情况下(除了特殊情况),在父级select box绑定的model将会是表达式的
value
。这意味着,在之前的例子中, item
是select元素的model。如果我们选择在select box中选择第二个元素,那么model应该为:
select as
,我们可以为select box指定一个不同的model,让我们看下面的例子:
ng-options="item.age as item.name for item in items"
item.name
作为显示文本,但是当我们选择它们中的一个,则select box的model(selectedItem)将会为对应的 item.age
。
label
group by group
for value
in array
<optgroup>
标签为options设置分组,但是在这里,可以指定ng-options基于 group
的值进行optgroups的渲染。让我们看下面的代码