Выбор Angularjs не помечает соответствующую модель как выбранную

У меня проблема с тем, что моя ngModel в select не отображается как выбранная. И идентификатор, и имя совпадают, но не работают, см. selectedState. Указание модели на фактический объект в массиве параметров работает, см. selectedState2. Без понятия, что происходит...

Скрипт: http://jsfiddle.net/fedorsmirnoff/b49n4Ldp/2/

<select ng-model="selectedState" ng-options="state.name for state in stateOptions"></select>

<select ng-model="selectedState2" ng-options="state.name for state in stateOptions"></select>

function MainCtrl($scope) {
 $scope.stateOptions = [
     {id: 1, name: "Alaska"},
     {id: 2, name: "Montana"},
     {id: 3, name: "Nebraska"},
     {id: 4, name: "Texas"}
  ]

 $scope.selectedState = {id: 2, name: "Montana"};

 $scope.selectedState2 = $scope.stateOptions[1];

}

person Micor    schedule 07.09.2014    source источник


Ответы (6)


Это связано с тем, что у каждого объекта есть собственный $hashKey, предоставленный Angular, который Angular использует для определения того, являются ли они одинаковыми. Вы создаете новый объект (с другим $hashKey) на $scope.selectedState. То, как вы установили его на $scope.selectedState2, правильно.

Вы также можете использовать track by, чтобы сделать Angular track с помощью state.id вместо объекта $hashKey:

<select ng-model="selectedState" ng-options="state.name for state in stateOptions track by state.id"></select>
person m59    schedule 07.09.2014

Если вы предоставляете объект в качестве модели, которая не содержит ссылку на существующий список, используйте track by с уникальным значением вашей модели, чтобы вместо использования пользовательского уникального $$hashKey ng-options использовал свойство которую вы предоставляете в отслеживании для отслеживания устанавливаемой модели ng.

  ng-options="state.name for state in stateOptions track by state.id"

Демо

Мало того, что это полезно при настройке ng-модели для любой ссылки, но также имеет большую эффективность производительности, особенно когда ваш список обновляется, элементы не будут удалены и воссозданы, вместо этого angular просто обновит существующий элемент.

Вот очень хороший пример для этого.

person PSL    schedule 07.09.2014

Команда Angular указала эту проблему в документации для ngSelect здесь:

Примечание. ngModel сравнивает по ссылке, а не по значению. Это важно при привязке к массиву объектов. См. пример в этом jsfiddle.

 $scope.options = [
    { label: 'one', value: 1 },
    { label: 'two', value: 2 }
  ];

  // Although this object has the same properties as the one in $scope.options,
  // Angular considers them different because it compares based on reference
  $scope.incorrectlySelected = { label: 'two', value: 2 };

  // Here we are referencing the same object, so Angular inits the select box correctly
  $scope.correctlySelected = $scope.options[1];
person Dalorzo    schedule 07.09.2014
comment
Это не совсем верно в отношении того, как работает ng-option, вы всегда можете что-то отследить и установить модель с этим значением свойства. Другой способ - использовать синтаксис value as name for item in ... Вы не всегда можете знать, к какому индексу принадлежат выбранные элементы в массиве (если только вы не выполняете цикл, чтобы получить совпадение, которое довольно неэффективно) - person PSL; 07.09.2014
comment
@PSL это основано на документации Angular Team, если она неполная. Angular Team также допустила ту же ошибку. - person Dalorzo; 07.09.2014

Когда вы устанавливаете $scope.selectedState, вы фактически создаете новый объект javascript, который не является элементом $scope.stateOptions. Следовательно, элемент select не будет выбирать соответствующий элемент из $scope.stateOptions.

Вы можете использовать «отслеживать» в выражении выбора, если вам нужно выбрать элементы по уникальному значению атрибута.

person Tharaka    schedule 07.09.2014

Попробуйте добавить Track by state.id в конце инструкции ng-options.

person Mindastic    schedule 07.09.2014

Я думаю, что Angular использует проверку ссылок вместо сравнения двух объектов с одинаковыми свойствами. В вашем случае $scope.selectedState2 возвращает другой объект. Я обычно использую understore, чтобы найти выбранный элемент из массива для инициализации.

person Hung Nguyen    schedule 07.09.2014