Невозможно установить выбранное значение 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'};
Список заполняется правильными 3 параметрами из объекта siteList
, но он не выбирает ходьбу по умолчанию, как я ожидал бы? Почему бы и нет?
Теперь, когда я изменяю это:
$scope.thisTour.site = { id: 2, name: 'walking'};
Для этого:
$scope.thisTour.site = $scope.siteList[1];
Теперь он работает. Зачем? Разве это не одно и то же?
Ответы
Ответ 1
Это потому, что angular ищет эквивалент объекта, чтобы связать его с вашим синтаксисом, а inyour case $scope.siteList[1]
не равен { id: 2, name: 'walking'};
(2 объекта равны, только если они указывают на одну и ту же ссылку). Вы можете обойти это разными способами, одним простым способом является использование синтаксиса track by
с ng-параметрами для указания трека на id
, который позволит отслеживать параметры опций ng с помощью указанного свойства связанного объекта чем сама ссылка на объект.
<select ng-model="thisTour.site"
ng-options="site.name for site in siteList track by site.id"></select>
Вы также можете использовать синтаксис, чтобы минимально установить ng-модель для указания только идентификатора, используя select в качестве части синтаксиса: -
Пример: -
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>
Ответ 2
Это не одно и то же, потому что объекты в 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", чтобы узнать больше.
Ответ 3
Поскольку вы используете весь объект в своем выборе, тогда, когда 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;
}
});
Это установит фактический объект в вашу переменную, позволяя его установить в выборе.
Ответ 4
Использовать в директиве ng-init. Когда выполняется инициализация, мы можем присвоить значение ng-модели.
<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>