ng-options не выбирает последний элемент в массиве параметров

У меня странная проблема, которую я не могу воспроизвести на Plunker. Когда в модели установлен первый параметр «пользователь», выбор отображает его правильно, и для него установлено значение «пользователь». Когда я загружаю другого пользователя с ролью: «admin», для выбора устанавливается пустая опция.

В моем контроллере я определяю:

$scope.roles = ['user', 'admin'];

Мой объект $scope.user выглядит так:

{
   "_id": "54f1f8f7e01249f0061c5088",
   "displayName": "Test1 User",
   "provider": "local",
   "username": "test1",
   "__v": 0,
   "updated": "2015-03-02T07:41:42.388Z",
   "created": "2015-02-28T17:20:55.893Z",
   "role": "admin",
   "profileImageURL": "modules/users/img/profile/default.png",
   "email": "[email protected]",
   "lastName": "User",
   "firstName": "Test1"
}

На мой взгляд:

<select id="role" class="form-control" data-ng-model="user.role" data-ng-options="role for role in roles"></select>

Когда я переворачиваю массив ролей $scope.roles = ['admin', 'user'];, администраторы отображаются правильно, а «пользователь» не будет установлен как выбранный.

Странно, если я добавлю третий элемент в массив $scope.roles = ['user', 'admin', 'joe'];, тогда первые два «пользователя» и «администратора» будут выбраны правильно, а последний «джо» — нет.

Есть идеи?

--- ОБНОВЛЕНИЕ ---

Сгенерированная разметка select выглядит следующим образом:

<select id="role" class="form-control ng-pristine ng-valid" data-ng-options="role for role in roles" data-ng-model="user.role">
    <option value="? string:joe ?"></option>
    <option value="0" selected="selected" label="admin">admin</option>
    <option value="1" label="user">user</option>
    <option value="2" label="joe">joe</option>
</select>

person orszaczky    schedule 02.03.2015    source источник
comment
Ну, как вы сказали, это не воспроизводимо с данной информацией. Попробуйте посмотреть реальную разметку за select — что вы там видите для последнего варианта?   -  person Ilya Luzyanin    schedule 02.03.2015
comment
Пожалуйста, смотрите разметку в обновлении вопроса   -  person orszaczky    schedule 02.03.2015
comment
Выглядит знакомо?   -  person Ilya Luzyanin    schedule 02.03.2015
comment
Да, спасибо за ссылку. По-видимому, это происходит, когда параметры находятся в массиве.   -  person orszaczky    schedule 02.03.2015
comment
Когда вы впервые загружаете страницу - какое начальное значение user.role? Я имею в виду в тот момент, когда angular выполняет привязку.   -  person Ilya Luzyanin    schedule 02.03.2015
comment
Как я могу это проверить? Я не устанавливаю какое-либо конкретное значение при инициализации.   -  person orszaczky    schedule 02.03.2015
comment
Ну, вы в основном объявляете свой объект $scope.user в контроллере и инициализируете его некоторым значением (может быть, пустым объектом), верно? Итак, попробуйте установить $scope.user.role= $scope.roles[0] в своем контроллере, чтобы он инициализировался с некоторым значением по умолчанию (ссылка на существующий индекс roles) до того, как будут получены фактические пользовательские данные.   -  person Ilya Luzyanin    schedule 02.03.2015
comment
К сожалению, это не имеет значения.   -  person orszaczky    schedule 02.03.2015


Ответы (4)


Я сделал все комбинации, которые вы предлагаете, но ошибка не возникает.

Пожалуйста, посмотрите мои тесты:

http://plnkr.co/edit/jzfhD3D60fhj8yFqBqgJ?p=preview

<h3>select</h3>
<select ng-model="role" ng-options="item for item in roles"></select>
<h3>original</h3>
<select id="role" class="form-control" data-ng-model="user.role" data-ng-options="role for role in roles"></select>

Попробуйте проверить версию angularjs. Возможно, может быть ошибка конкретной версии.

person Joao Polo    schedule 03.03.2015
comment
Вы действительно можете воспроизвести ошибку в верхнем выборе. Если вы проверите источник html, вы увидите первую пустую опцию: <option value="?" selected="selected" label=""></option> Мой пользовательский объект загружается из вызова API, и, по-видимому, это происходит, когда модель недоступна во время привязки. Как ни странно, этого не происходит, когда параметры находятся в объектах. - person orszaczky; 04.03.2015
comment
Я расширил ваш планкер, включив в него обходной путь на основе объектов, и попытался эмулировать вызов API с помощью setTimeout(). Интересная вещь происходит, когда вы открываете «старый» выбор, ничего не происходит, но как только вы открываете выбор «объекта», он обновляет привязку. Это не совсем то же самое поведение, которое было у меня, но оно показывает, что есть некоторая разница в обработке массивов и объектов Angular. См. здесь: plnkr.co/edit/WcAfmgwJkmJVfLFAPi2Z?p=preview - person orszaczky; 04.03.2015
comment
о первом случае: почему ваша модель изначально имеет нулевое значение, angularjs отражает это, создавая дополнительную «опцию» с этим начальным нулевым значением. когда вы выберете другую опцию, дополнительная опция исчезнет. Если вам нужно, вы можете создать внутреннюю часть, чтобы «выбрать» опцию со значением =, чтобы разрешить выбор нулевого значения. - person Joao Polo; 04.03.2015
comment
о втором случае... Вы не должны использовать setTimeout для angularjs напрямую. Вы можете использовать $timeout. Я изменил ваш пример, используя $timeout, и он работает лучше :-) ?p=предварительный просмотр - person Joao Polo; 04.03.2015
comment
Да, это было преднамеренно, смысл был в том, чтобы сделать что-то за рамками Angular, чтобы продемонстрировать непоследовательную обработку Angular простого массива и массива объектов. Возможно, есть лучшие витрины, но ваша демонстрация помогла мне сузить круг этого феномена! Спасибо за ваш вклад! :) - person orszaczky; 04.03.2015

Только что закончил бороться с этим. Моя модель $scope.details.source заполняется ajax, что вызывает проблему. (т. е. выбор не будет инициализироваться последним элементом в массиве, когда он будет возвращен ajax, другие значения инициализируются нормально). Я нашел работу вокруг. я имел

$scope.sources = ["1", "2", "3", "4", "5", "6", "7", "8"];
<select ng-model="details.source" ng-options="item for item in sources"> </select>

и изменил его на:

$scope.sources = [{index:0, value:"1"}, {index:1, value:"2"}, {index:2, value:"3"}, {index:3, value:"4"}, {index:4, value:"5"}, {index:5, value:"6"}, {index:6, value:"7"}, {index:7, value:"8"}];
<select ng-model="details.source" ng-options="item.index as item.value for item in sources"> </select>

Я обнаружил, что проблема не существовала, когда модель была инициализирована в контроллере, а не в ajax. Незнаю почему... но это работает.

person liteflier    schedule 17.08.2015

Я публикую обходной путь, но не решение и не объяснение описанной выше проблемы. Если у кого-то есть реальная информация, почему это происходит и как заставить это работать с массивами, поделитесь, пожалуйста, и я буду рад принять ее в качестве ответа.

Я изменил параметры с простого массива на массив объектов:

$scope.roles = [{name:'Admin',value:'admin'},{name:'User', value:'user'}];

И мой взгляд на:

<select data-ng-model="user.role" data-ng-options="role.value as role.name for role in roles"></select>

Спасибо Илье Лузянину за помощь и указания!

person orszaczky    schedule 02.03.2015

Возможно, поздно, но вот решение, которое мне помогло. Я всегда добавляю виртуальный невидимый параметр, который является последним в списке и никогда не выбирается.

<select class="form-control" 
        ng-options="r as r for r in myList | orderBy track by r"
        ng-model="item">
    <option ng-show="false"></option> <!-- TRICK: select last value too -->
</select>
person michal.jakubeczy    schedule 12.02.2019