Can't set selected value of ng-options

陌路散爱 提交于 2019-12-02 22:00:18

That is because angular looks for object equality to bind it with your syntax and inyour case $scope.siteList[1] is not equal to { id: 2, name: 'walking'}; (2 objects are equal only if they point to the same reference). You can get around this in many ways, one easy way is to use track by syntax with ng-options to specify track by id, which will enable ng-option's options to be tracked by the specified property of the bound object rather than the object reference itself.

<select ng-model="thisTour.site" 
    ng-options="site.name for site in siteList track by site.id"></select>

You could also use the syntax to minimally set the ng-model to specify only the id using select as part in the syntax:-

Example:-

ng-options="site.id as site.name for site in siteList"

and model would just be:-

 $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>

From documentation

trackexpr: - Used when working with an array of objects. The result of this expression will be used to identify the objects in the array. The trackexpr will most likely refer to the value variable (e.g. value.propertyName). With this the selection is preserved even when the options are recreated (e.g. reloaded from the server).

Also worth noting:

Do not use select as and track by in the same expression. They are not designed to work together.

This isn't the same thing because objects in javascript are passed by reference.

If you take the first example:

$scope.siteList = [
    { id: 1, name: 'cycling'},
    { id: 2, name: 'walking'},
    { id: 3, name: 'holidays'}
]

$scope.thisTour.site = { id: 2, name: 'walking'};

Then you do this:

$scope.thisTour.site.id = 3;
console.log($scope.siteList[1].id) // 2

In other words, whilst your two objects are equal in value, they aren't the same object. The ngOptions directive sees this, so would set thisTour.site to a blank value because it isn't one of the allowed options.

Google "passing by reference in javascript" to learn more.

Since you are using the entire object in your select then when Angular does it's comparison it is going to see if the objects are the same in order to set your select. I believe there is a way to change the functionality in how Angular does it's comparisions but I just loop through the select and do my own comparions similar to the below:

$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;
    }
});

This will set the actual object to your variable allowing it to be set in the select.

Use to ng-init directive .Which is execute initialy at a time we can assign value to 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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!