Почему AngularJS включает пустую опцию в select?

565

Я работаю с AngularJS в течение последних нескольких недель, и одна вещь, которая меня действительно беспокоит, заключается в том, что даже после попытки всех перестановок или конфигурации, определенных в спецификации, http://docs.angularjs.org/api/ng.directive:select, я все еще получаю пустую опцию в качестве первого дочернего элемента select.

Здесь Джейд:

select.span9(ng-model='form.type', required, ng-options='option.value as option.name for option in typeOptions');

Здесь контроллер:

$scope.typeOptions = [
    { name: 'Feature', value: 'feature' },
    { name: 'Bug', value: 'bug' },
    { name: 'Enhancement', value: 'enhancement' }
];

Наконец, здесь создается HTML-код:

<select ng-model="form.type" required="required" ng-options="option.value as option.name for option in typeOptions" class="span9 ng-pristine ng-invalid ng-invalid-required">
    <option value="?" selected="selected"></option>
    <option value="0">Feature</option>
    <option value="1">Bug</option>
    <option value="2">Enhancement</option>
</select>

Что мне нужно сделать, чтобы избавиться от него?

P.S.: Вещи тоже работают без этого, но это выглядит странно, если вы используете select2 без множественного выбора.

Теги:

24 ответа

605
Лучший ответ

Пустое option генерируется, когда значение, на которое ссылается ng-model, не существует в наборе параметров, переданных в ng-options. Это происходит, чтобы предотвратить случайный выбор модели: AngularJS может видеть, что исходная модель либо undefined, либо нет в наборе параметров и не хочет самостоятельно определять значение модели.

Если вы хотите избавиться от пустой опции, просто выберите начальное значение в вашем контроллере, например:

$scope.form.type = $scope.typeOptions[0].value;

Вот jsFiddle: http://jsfiddle.net/MTfRD/3/

Короче: пустая опция означает, что не выбрана допустимая модель (по действию я имею в виду: из набора параметров). Вам нужно выбрать допустимое значение модели, чтобы избавиться от этой пустой опции.

  • 6
    Я пытался с обоими $ scope.form.type = ''; и $ scope.form.type = $ scope.typeOptions [0], однако я все еще вижу это - <option value = "?" выбран = "выбрано"> </ вариант>
  • 2
    Извините, строка с HTML была настолько длинной, что я не заметил, что вы связываете имена, а не полные объекты. Пожалуйста, попробуйте с $ scope.typeOptions [0] .value, если это все еще не работает, я отправлю jsFiddle с примером.
Показать ещё 12 комментариев
204

Если вы хотите получить начальное значение, см. ответ @pkozlowski.opensource, который FYI также может быть реализован в представлении (а не в контроллере) с помощью ng-init:

<select ng-model="form.type" required="required" ng-init="form.type='bug'"
  ng-options="option.value as option.name for option in typeOptions" >
</select>

Если вы не хотите начального значения, "один элемент с жестким кодом со значением, установленным в пустую строку, может быть вложен в этот элемент. Затем этот элемент будет отображать нулевую или" не выбранную "опцию"

<select ng-model="form.type" required="required"
  ng-options="option.value as option.name for option in typeOptions" >
    <option style="display:none" value="">select a type</option>
</select>
  • 4
    @hugo, рабочая скрипка: jsfiddle.net/4qKyx/1 Обратите внимание, что отображается «выберите тип», но с ним не связано значение. И как только вы выберете что-то другое, вы больше этого не увидите. (Тест на Chrome.)
  • 0
    Это решение работает лучше всего для меня. Решение @ pkozlowski.opensource тоже работает, но в моем приложении оно также приводило к тому, что продукты не появлялись в корзине после. Спасибо!
Показать ещё 11 комментариев
109

Angular < 1.4

Для тех, кто относится к "null" как действительное значение для одного из параметров (так что представьте, что "null" является значением одного из элементов в typeOptions в примере ниже), я нашел, что самый простой способ убедиться что автоматически добавленная опция скрыта, заключается в использовании ng-if.

<select ng-options="option.value as option.name for option in typeOptions">
    <option value="" ng-if="false"></option>
</select>

Почему ng-if и не ng-hide? Поскольку вы хотите, чтобы селектора css, предназначенные для первой опции внутри, выбирали целевую "реальную" опцию, а не та, которая скрыта. Это становится полезным, когда вы используете транспортир для тестирования e2e и (по какой-либо причине) вы используете by.css() для выбора опций выбора.

Angular >= 1.4

Из-за рефакторинга директив select и options использование ng-if больше не является жизнеспособным вариантом, поэтому вам нужно перейти на ng-show="false", чтобы он снова работал.

  • 5
    Должен быть принятый ответ, потому что это правильное визуальное поведение для выбора. Вы помещаете size="5" в атрибуты select и видите, что ничего не выбрано! Как в элементе <select> по умолчанию! Я не могу понять, почему angular делает такую вещь для селектов без multiple атрибутов ...
  • 1
    Да, я согласен, это должен быть принятый ответ. Это «угловой путь». ng-if фактически удаляет элемент options из dom (когда false), поэтому это решение также работает во всех браузерах без «хакерского» кодирования (в отличие от ng-hide или ng-show).
Показать ещё 5 комментариев
33

Может быть полезно кому-то:

Если вы хотите использовать простые опции вместо ng-options, вы можете сделать следующее:

<select ng-model="sortorder" ng-init="sortorder='publish_date'">
  <option value="publish_date">Ascending</option>
  <option value="-publish_date">Descending</option>
</select>

Задайте модель встроенной. Используйте ng-init, чтобы избавиться от пустой опции

  • 0
    Я не смог найти четкого примера настройки опций ng с OBJECTS, а не с массивами JSON, и когда я пытаюсь «перевести» между ними, он не только не работает правильно, но и «молча», поэтому не получается Понятия не имею, что я делаю неправильно. Я наконец выбрал простой ng-repeat в теге option. Я знаю, что это не лучшая практика, но, по крайней мере, это работает. Если кто-то может указать мне на простой, легко заменяемый на детали, дружественный к angular-n00b РАБОЧИЙ пример, использующий опции ng с объектами данных (НЕ JSON), я был бы в восторге. Удваивается, если он также использует ng-init.
  • 0
    Я использую простые параметры, но в контроллере я не получаю значение выбранного выпадающего списка. Пример: я пробовал оповещение ($ scope.sortorder.value); и оповещение ($ scope.sortorder); оба дают неопределенные. Как получить выбранное значение здесь?
Показать ещё 1 комментарий
18

Среди множества ответов здесь я решил, что перережу решение, которое сработало для меня, и встретило все следующие условия:

  • предоставил заполнитель/приглашение, когда ng-модель является ложной (например, "- select region--" w. value="")
  • когда значение ng-модели ложно, и пользователь открывает раскрывающийся список опций, выбирается местозаполнитель (другие решения, упомянутые здесь, делают первый вариант выбранным, который может вводить в заблуждение)
  • позволяют пользователю отменить правильное значение, существенно выбрав значение ложности/значения по умолчанию

Изображение 3642

код

<select name="market_vertical" ng-model="vc.viewData.market_vertical"
    ng-options="opt as (opt | capitalizeFirst) for opt in vc.adminData.regions">

    <option ng-selected="true" value="">select a market vertical</option>
</select>

ЦСИ

оригинал q & a - https://stackoverflow.com/questions/17892220/angularjs-and-select-default-selected-options-are-removed

  • 0
    это не работает, если значение равно нулю
  • 0
    Вы имеете в виду, если по умолчанию <option ng-selected="true" value="null"> ?
Показать ещё 1 комментарий
17

Что-то подобное произошло со мной и было вызвано обновлением до angular 1.5. ng-init похоже, анализируется для типа в более новых версиях Angular. В более раннем angular ng-init="myModelName=600" будет отображаться опция со значением "600", то есть <option value="600">First</option>, но в angular 1.5 она не найдет этого, поскольку, похоже, ожидает найти параметр со значением 600, т.е. <option value=600>First</option>. angular затем вставляет случайный первый элемент:

<option value="? number:600 ?"></option>

Angular < 1.2.x

<select ng-model="myModelName" ng-init="myModelName=600">
  <option value="600">First</option>
  <option value="700">Second</option>
</select>

Angular > 1.2

<select ng-model="myModelName" ng-init="myModelName='600'">
  <option value="600">First</option>
  <option value="700">Second</option>
</select>
  • 1
    Спасибо! В моем случае я не могу использовать ng-init (без значения по умолчанию), поэтому я преобразовал свою модель в строку, и это сработало!
  • 0
    Лучший ответ на эту проблему ...
Показать ещё 2 комментария
14

Быстрое решение:

select option:empty { display:none }

Надеюсь, это поможет кому-то. В идеале выбранный ответ должен быть подходом, но если в случае невозможности он должен работать как патч.

  • 2
    По моим тестам, это будет работать только в Chrome (новый Chrome, кроме того) и Firefox. IE и Safari ломаются. Не знаю об опере и других браузерах. В любом случае, это не очень хорошее решение, к сожалению.
  • 0
    где мы должны поместить это в html до закрытия <select> или в js
Показать ещё 4 комментария
13

Да ng-model создаст пустое значение параметра, когда свойство ng-model undefined. Мы можем избежать этого, если мы назначим объект ng-model

Пример

angular кодирование

$scope.collections = [
    { name: 'Feature', value: 'feature' }, 
    { name: 'Bug', value: 'bug' }, 
    { name: 'Enhancement', value: 'enhancement'}
];

$scope.selectedOption = $scope.collections[0];


<select class='form-control' data-ng-model='selectedOption' data-ng-options='item as item.name for item in collections'></select>

Важное примечание:

Назначить объект массива как $scope.collections [0] или $scope.collections [1] в ng-model, не использовать свойства объекта. если вы получаете значение опции выбора с сервера, используя функцию обратного вызова, назначьте объект ng-model

ПРИМЕЧАНИЕ из документа Angular

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

Я много раз пытался найти его.

8

Хотя оба ответа @pkozlowski.opensource и @Mark верны, я хотел бы поделиться своей измененной версией, где всегда выбираю первый элемент в списке, независимо от его значения:

<select ng-options="option.value as option.name for option in typeOptions" ng-init="form.type=typeOptions[0].value">
</select>
3

Я использую Angular 1.4x, и я нашел этот пример, поэтому я использовал ng-init для установки начального значения в select:

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.id for item in items"></select>
3

Хорошо, на самом деле ответ прост: если опция Angular не распознана, она содержит тупую. Что вы делаете неправильно, когда вы используете ng-options, он читает объект, скажем [{ id: 10, name: test }, { id: 11, name: test2 }] right?

Это то, что должно оценивать ваше значение модели как равное, например, вы хотите, чтобы выбранное значение было равным 10, вам нужно установить свою модель на значение, подобное { id: 10, name: test }, чтобы выбрать 10, поэтому оно НЕ будет создавать это мусор.

Надеюсь, что это поможет всем понять, мне было тяжело попробовать:)

3

Простое решение - установить опцию с пустым значением "". Я обнаружил, что это исключает дополнительную опцию undefined.

  • 4
    Doenst work @ 1.4.3, он просто добавляет 2 пустые опции в форму
3


Я столкнулся с той же проблемой. Если вы публикуете форму angular с обычной почтой, вы столкнетесь с этой проблемой, так как angular не позволяет устанавливать значения для параметров в том виде, в котором вы использовали. Если вы получите значение "form.type", то вы найдете нужное значение. Вы должны опубликовать объект angular, это не сообщение формы.

2

Это сработало для меня

<select ng-init="basicProfile.casteId" ng-model="basicProfile.casteId" class="form-control">
     <option value="0">Select Caste....</option>
     <option data-ng-repeat="option in formCastes" value="{{option.id}}">{{option.casteName}}</option>
 </select>
  • 0
    Просто добавляет опцию в список и, к сожалению, оставляет пустое место.
1

Это прекрасно работает

<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
    <option style="display:none" value=""></option>
</select>

способ, которым он работает, заключается в том, что это дает первый вариант для отображения перед тем, как выбрать что-то, а display:none удаляет его из раскрывающегося списка, поэтому, если вы хотите, вы можете сделать

<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
    <option style="display:none" value="">select an option...</option>
</select>

и это даст вам select and option перед выбором, но после его выбора он исчезнет, ​​и он не появится в раскрывающемся списке.

  • 0
    На самом деле вы не отвечаете на сам вопрос, что еще хуже, вы просто скрываете элемент.
0

Единственное, что сработало для меня, это использовать track by в ng-options, например:

 <select class="dropdown" ng-model="selectedUserTable" ng-options="option.Id as option.Name for option in userTables track by option.Id">

  • 0
    если я использую эту ng-option получи последнее значение массива, которое я хочу установить значение option select . Это не решено :(
0

Привет, у меня были ссылки на jQuery для мобильных устройств, и я удалил их. С jQuery mobile любое исправление не срабатывало для меня. (Отлично, если кто-то может объяснить конфликт между jQuery Mobile и Angular JS)

https://guntucomputerhacks.blogspot.com.au/2017/10/angular-js-drop-down-first-options-vs.html

0

У меня была та же проблема, i (удаленная "ng-model" ) изменила это:

<select ng-model="mapayear" id="mapayear" name="mapayear" style="  display:inline-block !important;  max-width: 20%;" class="form-control">
  <option id="removable" hidden> Selecione u </option>
    <option selected ng-repeat="x in anos" value="{{ x.ano }}">{{ x.ano }}
</option>
</select>

:

<select id="mapayear" name="mapayear" style="  display:inline-block !important;  max-width: 20%;" class="form-control">
  <option id="removable" hidden> Selecione u </option>
    <option selected ng-repeat="x in anos" value="{{ x.ano }}">{{ x.ano }}
</option>
</select>

теперь он работает, но в моем случае это было причиной того, что Ive удалил эту область из ng.controller, проверьте, не выполнил ли u то же самое.

0

Если вы используете ng-init свою модель для решения этой проблемы:

<select ng-model="foo" ng-app ng-init="foo='2'">
0

Измельчить решение с помощью jQuery, если вы не контролируете параметры

HTML:

<select id="selector" ng-select="selector" data-ng-init=init() >
...
</select>

JS:

$scope.init = function () {
    jQuery('#selector option:first').remove();
    $scope.selector=jQuery('#selector option:first').val();
}
  • 0
    Паскаль, кто-то отверг тебя, потому что это решение jQuery, а не AngularJs
  • 1
    @ Mawg или потому что это огромный обходной путь.
Показать ещё 1 комментарий
0

Простое решение

<select ng-model='form.type' required><options>
<option ng-repeat="tp in typeOptions" ng-selected="    
{{form.type==tp.value?true:false}}" value="{{tp.value}}">{{tp.name}}</option>

0

Я хотел бы добавить, что если начальное значение происходит от привязки от какого-либо родительского элемента или 1.5 компонента, убедитесь, что соответствующий тип передан. При использовании @ в привязке передаваемая переменная будет строкой, и если, например, есть варианты. целые числа, тогда появится пустая опция.

Либо правильно проанализировать значение в init, либо привязать его к <, а не @ (менее рекомендуется для производительности, если это необходимо).

0

Вот исправление:

для образца данных типа:

financeRef.pageCount = [{listCount:10,listName:modelStrings.COMMON_TEN_PAGE},    
{listCount:25,listName:modelStrings.COMMON_TWENTYFIVE_PAGE},
{listCount:50,listName:modelStrings.COMMON_FIFTY_PAGE}];

Опция выбора должна быть такой: -

<select ng-model="financeRef.financeLimit" ng-change="financeRef.updateRecords(1)" 
class="perPageCount" ng-show="financeRef.showTable" ng-init="financeRef.financeLimit=10"
ng-options="value.listCount as value.listName for  value in financeRef.pageCount"
></select>

Точка, когда мы пишем value.listCount как value.listName, автоматически заполняет текст в value.listName, но значение выбранного параметра равно value.listCount, хотя значения my show normal 0,1,2.. и т.д.

В моем случае financeRef.financeLimit на самом деле захватывает value.listCount, и я могу динамически манипулировать контроллером.

0

Попробуйте это в своем контроллере в том же порядке:

$scope.typeOptions = [
    { name: 'Feature', value: 'feature' }, 
    { name: 'Bug', value: 'bug' }, 
    { name: 'Enhancement', value: 'enhancement' }
];
$scope.form.type = $scope.typeOptions[0];
  • 0
    Я попробовал ваш метод, но, к сожалению, не смог заставить его работать. Можете ли вы взглянуть на эту скрипку? jsfiddle.net/5PdaX

Ещё вопросы

Сообщество Overcoder
Наверх
Меню