我正在尝试填充下拉选择选项列表,并使用ng-model和ng-options设置默认选定值。
我在视图中有以下代码:
<select ng-model="thisTour.site" ng-options="site.name for site in siteList"></select>
在我的控制器中:
$scope.siteList = [
{ id: 1, name: 'cycling'},
{ id: 2, name: 'walking'},
{ id: 3, name: 'holidays'}
]
$scope.thisTour.site = { id: 2, name: 'walking'};
列表中正在填充siteList
对象中正确的3个选项,但默认情况下它没有按照我的预期选择行走?为什么不呢?
现在,当我改变这个时:
$scope.thisTour.site = { id: 2, name: 'walking'};
对此:
$scope.thisTour.site = $scope.siteList[1];
现在它有效。为什么?这不是一回事吗?
答案 0 :(得分:44)
这是因为angular查找对象相等以将其与您的语法绑定,并且您的案例$scope.siteList[1]
不等于{ id: 2, name: 'walking'};
(只有当两个对象指向相同的引用时它们才相等)。您可以通过多种方式解决这个问题,一种简单的方法是使用track by
语法和ng-options指定跟踪id
,这将使ng-option的选项能够被指定的属性跟踪。绑定对象而不是对象引用本身。
<select ng-model="thisTour.site"
ng-options="site.name for site in siteList track by site.id"></select>
您还可以使用语法最小化设置ng-model,以便在语法中使用 select as 部分仅指定id: -
实施例: -
ng-options="site.id as site.name for site in siteList"
和模型就是: -
$scope.thisTour.site = 2;
angular.module('app', []).controller('ctrl', function($scope){
$scope.thisTour = {};
$scope.siteList = [
{ id: 1, name: 'cycling'},
{ id: 2, name: 'walking'},
{ id: 3, name: 'holidays'}
]
$scope.thisTour.site = { id: 2, name: 'walking'};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select ng-model="thisTour.site" ng-options="site.name for site in siteList track by site.id"></select>
{{thisTour.site}}
</div>
trackexpr: - 在处理对象数组时使用。此表达式的结果将用于标识数组中的对象。 trackexpr很可能会引用值变量(例如value.propertyName)。这样,即使重新创建选项(例如,从服务器重新加载),也会保留选择。
另外值得注意的是:
请勿在同一表达式中使用select as和track by。它们并非旨在协同工作。
答案 1 :(得分:3)
这不是一回事,因为javascript中的对象通过引用传递。
如果你拿第一个例子:
$scope.siteList = [
{ id: 1, name: 'cycling'},
{ id: 2, name: 'walking'},
{ id: 3, name: 'holidays'}
]
$scope.thisTour.site = { id: 2, name: 'walking'};
然后你这样做:
$scope.thisTour.site.id = 3;
console.log($scope.siteList[1].id) // 2
换句话说,当你的两个物体在值中相等时,它们不是同一个物体。 ngOptions
指令会看到这一点,因此会将thisTour.site
设置为空值,因为它不是允许的选项之一。
Google“通过javascript中的引用传递”以了解更多信息。
答案 2 :(得分:1)
由于您在选择中使用了整个对象,因此当Angular进行比较时,它将查看对象是否相同以设置您的选择。我相信有一种方法可以改变Angular如何进行比较的功能,但我只是循环选择并进行类似下面的比较:
$scope.siteList = [
{ id: 1, name: 'cycling'},
{ id: 2, name: 'walking'},
{ id: 3, name: 'holidays'}
]
angular.forEach($scope.siteList, function(site, index) {
if (site.id == 2) {
$scope.thisTour.site = site;
}
});
这会将实际对象设置为您的变量,允许在select中设置它。
答案 3 :(得分:0)
用于ng-init指令。在我们可以为ng-model分配值的时候首先执行。
<div ng-init="thisTour.site = siteList[position]">
<select ng-model="thisTour.site" ng-options="site.name for site in siteList track by site.id"></select>
</div>