Чому AngularJS включає порожню опцію у виборі?


652

Я працював з 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>

Що мені потрібно зробити, щоб позбутися цього?

PS: Також речі працюють і без цього, але це виглядає дивним чином, якщо ви користуєтеся select2 без багаторазового вибору.

Відповіді:


646

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

Якщо ви хочете позбутися від порожньої опції, просто виберіть початкове значення у своєму контролері, наприклад:

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

Ось jsFiddle: http://jsfiddle.net/MTfRD/3/

Коротше кажучи: порожній варіант означає, що не обрана жодна дійсна модель (мається на увазі, я маю на увазі: з набору параметрів). Вам потрібно вибрати дійсне значення моделі, щоб позбутися цієї порожньої опції.


7
Я спробував і з $ range.form.type = ''; і $ range.form.type = $ range.typeOptions [0], однак я все ще бачу це - <значення параметра = "?" selected = "selected"> </option>
Sudhanshu

5
Іноді насправді не має сенсу мати ці дані в СП. Якщо саме сервер прийняв рішення про те, що було в цьому виді, чому СС повинен дублювати це?
heneryville

11
На жаль, це не працює, якщо ви використовуєте масив і nullє одним із ваших значень.
vpiTriumph

6
Чи можна додати текст всередину порожнього, <option>так чіткого кутового, що генерується щось на кшталт<option value="?">Select an option</option>
RPDeshaies

3
@ Tareck117 просто написав <option value="">Select an option</option>нульове значення списку опцій. Не потрібно? -Характер.
Себастьян

235

Якщо ви хочете початкового значення, див. Відповідь @ 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.)
Марк Райкок

1
@MarkRajcok - відмінна пропозиція! я натрапив на іншу проблему, використовуючи ваш приклад із включенням директиви. Не могли б ви подивитись? plnkr.co/edit/efaZdEQlNfoDihk1R1zc?p=preview
Jan-Terje Sørensen

2
Проблема з цим ви можете вибрати з допомогою клавіатури, див stackoverflow.com/a/8442831/57344 рішення
HaveAGuess

2
Це може працювати наразі, але кутова документація спеціально рекомендує не використовувати ng-init для нічого, крім ng-повтору - див. Docs.angularjs.org/api/ng/directive/ngInit
Ед Норріс

3
Не працює в IE10, "виберіть тип" завжди видно і вибирається.
Робін

121

Кутовий <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-якщо і не ng-приховати? Тому що ви хочете, щоб селектори css, які орієнтувались на перший варіант всередині, виберіть, щоб націлити на "реальний" варіант, а не на той, що приховано. Це стає корисним, коли ви використовуєте транспортир для тестування e2e і (з будь-якої причини) ви використовуєте by.css () для націлювання параметрів вибору.

Кутова> = 1,4

Через рефакторинг директив для вибору та параметрів використання ng-ifбільше не є життєздатним варіантом, тому вам доведеться ng-show="false"звернутися, щоб знов працювати.


5
Повинна бути прийнята відповідь, оскільки це правильна візуальна поведінка для вибраного. Ви ставите size="5"до атрибутів select і ви бачите, що нічого не вибрано! Як у замовчуванні <select>-Element! Я не можу зрозуміти, чому кутовий робить таке для вибраних без multipleатрибутів ...
Себастьян

1
Так, я згоден, це повинна бути прийнята відповідь. Це "кутовий шлях". ng-if насправді видаляє елемент параметра з дому (коли невірно), тому це рішення також працює у всіх браузерах без "хакі" кодування (всупереч ng-скривати або ng-шоу).
Sander_P

2
@Sander_P за визначенням, це рішення є "хакі" кодування на мою думку (поставити щось у домі, щоб хитрощів зняти його), але ви праві, все одно це "найкраще" рішення. "Ще кращим" рішенням було б дозволити вибір фрегіна, який не має значення! Якого біса? Це не так, як це крайній сценарій.
dudewad

@dudewad: з Angular 1.4 все може працювати краще. З блогу AngularJS за 1.4.0: "ngOptions було повністю відновлено, щоб дозволити виправити ряд набридливих помилок",
Sander_P

1
Ха-ха "дратівливі клопи". Добре. Ну, я все ще трохи скупий, коли справа стосується модернізації за 3 дні до доставки, тому я зараз буду тримати ваше рішення, яке, здається, працює плавно. Помічено на майбутнє, хоча :) Дякую!
dudewad

36

Може бути корисним для когось:

Якщо ви хочете використовувати прості параметри замість ng-параметрів, ви можете зробити наступне:

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

Встановіть модель в рядку. Використовуйте ng-init, щоб позбутися від порожньої опції


Я не зміг знайти чіткий приклад налаштування ng-параметрів за допомогою OBJECTS, а не масивів JSON, і коли я намагаюся "перекласти" між ними, це не тільки не виходить правильно, але й "мовчки" не виходить Я не маю поняття, що я роблю не так. Нарешті я вибрав просте ng-повторення у тезі опцій. Я знаю, що це не найкраща практика, але принаймні це РОБОТА. Якщо хтось може вказати мені на простого, легко міняється на деталі, прикладу РОБОЧОГО зручного для кутових n00b використання ng-опцій із об’єктами даних (НЕ JSON), я був би в захваті. Подвійний піднятий, якщо він також використовує ng-init.
код-суші

Я використовую прості параметри, але в контролері я не отримую значення обраного спаду. Напр .: я спробував оповістити ($ range.sortorder.value); і попередження ($ range.sortorder); обидва дає невизначений. Як отримати тут вибране значення?
Маверик Різ

Дуже дякую за це. Я збирався написати абсолютно непотрібний об’єкт у контролері, який мені не потрібен, мені просто потрібен був простий вибір. Дякую ще раз.
Мухаммед бен Юсрат

22

Щось подібне сталося і зі мною, і це було викликано оновленням до кутової 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>. Кутовий буде потім вставити випадковий перший елемент:

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

Кутовий <1,2.x

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

Кутовий> 1.2

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

1
Дякую! У моєму випадку я не можу використовувати ng-init (значення за замовчуванням), тому я закинув свою модель на рядок, і вона спрацювала!
Родріго Грача

Дуже корисно для мого питання з виробництва додатків Дякуємо @Nabil Boag
Venki

3
Це працює, звичайно, але тим краще варіанти, щоб використовувати ng-value="600"в optionзамість value. Він розбере його на число, і вам не доведеться конвертувати свої значення, як ви робите зараз :)
Макс

@Max Я спробував багато відповідей на високу цінність, але жоден не спрацював, поки я не знайшов твою. Дякую.
Андрій

21

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

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

введіть тут опис зображення

код

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

src

оригінал q & a - https://stackoverflow.com/a/32880941/1121919


Ви маєте на увазі, якщо за замовчуванням є <option ng-selected="true" value="null">?
jusopi

Я маю на увазі, якщо значення ng-моделі встановлено як нульове, кутове створення та порожній варіант у виборі
Flezcano

16

Швидке рішення:

select option:empty { display:none }

Сподіваюся, це комусь допоможе. В ідеалі, обрана відповідь має бути підходом, але якщо це неможливо, то слід працювати як виправлення.


2
За моїм тестуванням, це працюватиме лише в Chrome (новий Chrome, поверх цього) та Firefox. IE і Safari ламаються. Не знаєте про опери та інші крайові браузери. Так чи інакше, це , на жаль, не гарне рішення.
dudewad

де ми повинні розмістити це в html перед закриттям <select> або ще в js
H Varma

1
@HVarma Це правило CSS. Розмістіть його в таблиці стилів або всередині тегу <style>
KK

@KK stackoverflow.com/questions/48355599 / ... Чи можете ви перевірити це?
Sudarshan Kalebere

14

Так, ng-model створить порожнє значення параметра, коли властивість ng-model не визначена. Ми можемо цього уникнути, якщо призначити об’єкт ng-моделі

Приклад

кутове кодування

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

Важлива примітка:

Призначте об’єкт масиву, як $ range.collections [0] або $ range.collections [1], для ng-моделі, не використовуйте властивості об'єкта. якщо ви отримуєте значення вибору параметра з сервера, використовуючи функцію зворотного дзвінка, призначте об'єкт ng-моделі

ПРИМІТКА з кутового документа

Примітка: 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>

4

Я використовую 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


Я зіткнувся з тим же питанням. Якщо ви публікуєте кутову форму за допомогою звичайного допису, тоді ви зіткнетеся з цією проблемою, оскільки кутовий не дозволяє встановлювати значення параметрів таким чином, яким ви користувались. Якщо ви отримаєте значення "form.type", то ви знайдете потрібне значення. Ви повинні розміщувати кутовий об'єкт, а не розміщувати форму.


3

Просте рішення - встановити параметр із порожнім значенням. ""Я виявив, що це виключає зайвий неозначений варіант.


5
Doenst робота @ 1.4.3, він просто додає 2 порожні варіанти до форми
Денні Мюллер

3

Гаразд, відповідь насправді простий: коли є варіант, не розпізнаний Angular, він включає тупу. Те, що ви робите неправильно, це, коли ви використовуєте ng-параметри, воно читає об'єкт, скажімо[{ id: 10, name: test }, { id: 11, name: test2 }] right?

Це те, що має значення вашої моделі, щоб оцінити її як рівну, скажімо, що ви бажаєте, щоб вибране значення було 10, вам потрібно встановити модель як таке, як { id: 10, name: test } вибрано 10, тому воно НЕ створюватиме цей смітник.

Сподіваюся, це допомагає зрозуміти всім, я намагався грубо намагатися :)


2

Це рішення працює для мене:

<select ng-model="mymodel">    
   <option ng-value="''" style="display:none;" selected>Country</option>
   <option value="US">USA</option>
</select>

Downvote може бути через те, що застосування CSS до елементів параметрів працює не у всіх браузерах.
Кафосо

Я тільки тестував його на Chrome, FireFox, Safari та Edge - все працює.
МММ

@MMM "усі браузери" включає IE. Багато користувачів досі застрягли з IE 10 та 11, і саме тому, що сталося пониження, сталося. Chrome, fF, Saf та Edge - це не всі браузери.
ПКД

1

Це працювало для мене

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

Просто додає параметр у список і на жаль залишає порожній простір.
AMontpetit

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

Спробуйте це у своєму контролері в тому ж порядку:

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

Я спробував ваш метод, але, на жаль, не зміг змусити його працювати. Можете поглянути на цю загадку. jsfiddle.net/5PdaX
Sinha

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 хоча значення, які моє показують, звичайні 0,1,2 .. і так далі !!!

У моєму випадку, financeRef.financeLimitфактично захоплює, value.listCountі я можу робити маніпуляції в контролері динамічно.


0

Я хотів би додати, що якщо початкове значення походить від прив'язки з якогось батьківського елемента або 1,5 компонента, переконайтеся, що передано належний тип. Якщо використовується@ для прив'язки, передана змінна буде рядковою, а якщо параметри є, наприклад. цілі числа, тоді з'явиться порожня опція.

Або правильно розбирайте значення в init, або зв'язуючи з <і не @(менш рекомендується для виконання, якщо не потрібно).


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

Шліфування рішення з 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();
}

Паскаль, хтось прихильнив вас, тому що це рішення jQuery, а не AngularJs
Мавг каже, що поверніть Моніку

Питання пропонується розкопати більше кутових ...: - /
Саху V Кумар

0

Якщо ви використовуєте модель ng-init для вирішення цієї проблеми:

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

0

У мене була така ж проблема, я (вилучив "ng-модель") змінив це:

<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, перевірте, чи не зробили ви те ж саме.


0

Привіт, у мене були кілька мобільних посилань jQUery, і я їх видалив. З мобільним jQuery жоден з вищезазначених виправлень не працював для мене. (Чудово, якщо хтось може пояснити конфлікт між jQuery Mobile та Angular JS)

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


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


якщо я використовую це ng-optionотримати останнє значення масиву , який я хочу , щоб встановлене значення optionз select. Це не вирішилось :(
rufatZZ

0

Перегляньте приклад із документації на angularjs, як подолати ці проблеми.

  1. Перейдіть до цього посилання на документацію тут
  2. Знайдіть " Прив'язка вибору до нерядкового значення за допомогою розбору / форматування ngModel "
  3. Тут ви можете бачити, що директива під назвою " convertToNumber " вирішує проблему.

Це працює для мене. Можна також побачити, як це працює тут


0

Ми можемо використовувати CSS, щоб приховати перший варіант, але він не працюватиме в IE 10, 11. Найкращий спосіб - видалити елемент за допомогою Jquery. Це рішення працює для головного браузера, протестованого в хромі та IE10, 11

Крім того, якщо ви використовуєте кутовий, колись використовується setTimeout

$scope.RemoveFirstOptionElement = function (element) {
    setTimeout(function () {
        $(element.children()[0]).remove();
    }, 0);
};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.