无法设置ng-options的选定值

时间:2014-12-16 21:31:06

标签: angularjs angularjs-ng-options

我正在尝试填充下拉选择选项列表,并使用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];

现在它有效。为什么?这不是一回事吗?

4 个答案:

答案 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>

来自documentation

  

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>