Warum enthält AngularJS eine leere Option in select?


652

Ich habe in den letzten Wochen mit AngularJS gearbeitet, und das einzige, was mich wirklich stört, ist, dass ich selbst nach dem Ausprobieren aller Permutationen oder der in der Spezifikation unter http://docs.angularjs.org/api/ng definierten Konfiguration .directive: select , ich erhalte immer noch eine leere Option als erstes untergeordnetes Element des select-Elements.

Hier ist die Jade:

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

Hier der Controller:

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

Schließlich ist hier der HTML-Code, der generiert wird:

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

Was muss ich tun, um es loszuwerden?

PS: Die Dinge funktionieren auch ohne dies, aber es sieht nur seltsam aus, wenn Sie select2 ohne Mehrfachauswahl verwenden.

Antworten:


646

Das Leerzeichen optionwird generiert, wenn ein Wert, auf den verwiesen wird ng-model, in einer Reihe von Optionen, an die übergeben wird, nicht vorhanden ist ng-options. Dies verhindert eine versehentliche Modellauswahl: AngularJS kann erkennen, dass das ursprüngliche Modell entweder undefiniert ist oder nicht in den Optionen enthalten ist, und möchte den Modellwert nicht selbst bestimmen.

Wenn Sie die leere Option entfernen möchten, wählen Sie einfach einen Anfangswert in Ihrem Controller aus, etwa:

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

Hier ist die jsFiddle: http://jsfiddle.net/MTfRD/3/

Kurz gesagt: Die leere Option bedeutet, dass kein gültiges Modell ausgewählt ist (mit gültig meine ich: aus dem Satz von Optionen). Sie müssen einen gültigen Modellwert auswählen, um diese leere Option zu entfernen.


7
Ich habe es mit beiden versucht: $ scope.form.type = ''; und $ scope.form.type = $ scope.typeOptions [0], aber ich sehe immer noch dies - <option value = "?" selected = "selected"> </ option>
Sudhanshu

5
Manchmal ist es wirklich nicht sinnvoll, diese Daten im JS zu haben. Wenn es der Server ist, der die Entscheidung darüber getroffen hat, was in dieser Auswahl enthalten ist, warum sollte der JS diese duplizieren müssen?
Henryville

11
Dies funktioniert leider nicht, wenn Sie ein Array verwenden und nullist einer Ihrer Werte.
vpiTriumph

6
Ist es möglich, einen Text in das leere hinzuzufügen, <option>so dass der Winkel so etwas wie<option value="?">Select an option</option>
RPDeshaies

3
@ Tareck117 nur wirte <option value="">Select an option</option>das ist der Nullwert der Optionsliste. Keine Notwendigkeit für? -Zeichen.
Sebastian

235

Wenn Sie einen Anfangswert wünschen, lesen Sie die Antwort von @ pkozlowski.opensource, die zu Ihrer Information auch in der Ansicht (und nicht in der Steuerung) mit ng-init implementiert werden kann:

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

Wenn Sie keinen Anfangswert möchten, kann "ein einzelnes fest codiertes Element, dessen Wert auf eine leere Zeichenfolge festgelegt ist, in das Element verschachtelt werden. Dieses Element repräsentiert dann die Option null oder" nicht ausgewählt "":

<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, Working Fiddle: jsfiddle.net/4qKyx/1 Beachten Sie, dass "Typ auswählen" angezeigt wird, aber kein Wert damit verknüpft ist. Und wenn Sie etwas anderes ausgewählt haben, werden Sie es nicht mehr sehen. (Test auf Chrome.)
Mark Rajcok

1
@ MarkRajcok - ausgezeichneter Vorschlag! Ich bin über ein anderes Problem gestolpert, das Ihr Beispiel mit der ausschließenden Richtlinie verwendet. Könnten Sie bitte einen Blick darauf werfen? plnkr.co/edit/efaZdEQlNfoDihk1R1zc?p=preview
Jan-Terje Sørensen

2
Problem dabei ist, dass Sie immer noch mit der Tastatur auswählen können, siehe stackoverflow.com/a/8442831/57344 Lösung
HaveAGuess

2
Dies mag vorerst
Ed Norris

3
Funktioniert nicht in IE10, das "Typ auswählen" ist immer sichtbar und auswählbar.
Robin

121

Winkel <1,4

Für alle da draußen, die "null" als gültigen Wert für eine der Optionen behandeln (stellen Sie sich also vor, dass "null" ein Wert eines der Elemente in typeOptions im folgenden Beispiel ist), habe ich den einfachsten Weg gefunden, um sicherzustellen, dass dieser automatisch hinzugefügt wird Option ist versteckt ist ng-if zu verwenden.

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

Warum ng-if und nicht ng-hide? Da Sie CSS-Selektoren möchten, die auf die erste Option oben abzielen, wählen Sie "echte" Option, nicht die versteckte. Dies ist nützlich, wenn Sie Winkelmesser für e2e-Tests verwenden und (aus welchen Gründen auch immer) by.css () verwenden, um ausgewählte Optionen als Ziel festzulegen.

Winkel> = 1,4

Aufgrund des Refactorings der Direktiven select und options ist die Verwendung ng-ifnicht mehr sinnvoll, sodass Sie sich an wenden müssen ng-show="false", damit es wieder funktioniert.


5
Sollte die akzeptierte Antwort sein, da dies das richtige visuelle Verhalten für die Auswahl ist. Sie setzen size="5"die ausgewählten Attribute und Sie können sehen, dass nichts ausgewählt ist! Wie in einem Standard- <select>Element! Ich kann nicht verstehen, warum Angular so etwas für Selects ohne multipleAttribut tut ...
Sebastian

1
Ja, ich stimme zu, dies sollte die akzeptierte Antwort sein. Dies ist der "Winkelweg". ng-if entfernt tatsächlich das options-Element aus dem dom (wenn false), sodass diese Lösung auch in allen Browsern ohne "hacky" -Codierung funktioniert (im Gegensatz zu ng-hide oder ng-show).
Sander_P

2
@Sander_P per definitionem ist diese lösung meiner meinung nach "hacky" codierung (etwas in den dom setzen, um eckig herauszunehmen), aber du hast recht, es ist immer noch die "beste" lösung. Die "noch bessere" Lösung wäre, eine verdammte Auswahl zuzulassen, die keinen Wert hat! Was zum Teufel? Es ist nicht so, dass dies ein Rand-Szenario ist.
Dudewad

@dudewad: Mit Angular 1.4 könnte es besser laufen. Aus dem AngularJS-Blog für 1.4.0: "ngOptions wurde komplett überarbeitet, damit einige nervige Fehler behoben werden können"
Sander_P

1
Haha "nervige Käfer". Okay. Nun, ich bin immer noch ein wenig skiddisch, wenn es darum geht, 3 Tage vor der Auslieferung ein Upgrade durchzuführen, also werde ich vorerst bei Ihrer Lösung bleiben, die schwimmend zu funktionieren scheint. Bekannt für die Zukunft :) Danke!
Dudewad

36

Vielleicht nützlich für jemanden:

Wenn Sie einfache Optionen anstelle von ng-Optionen verwenden möchten, können Sie Folgendes tun:

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

Stellen Sie das Modell inline ein. Verwenden Sie ng-init, um die leere Option zu entfernen


Ich konnte kein klares Beispiel für das Einrichten von ng-Optionen mit OBJECTS anstelle von JSON-Arrays finden. Wenn ich versuche, zwischen den beiden zu "übersetzen", kommt dies nicht nur nicht richtig heraus, sondern schlägt auch "lautlos" fehl Ich habe keine Ahnung, was ich falsch mache. Ich habe mich schließlich für die einfache Wiederholung in einem Options-Tag entschieden. Ich weiß, dass es keine bewährte Methode ist, aber es funktioniert zumindest. Wenn mich jemand auf ein einfaches, leicht austauschbares, eckig-n00b-freundliches ARBEITSbeispiel mit ng-Optionen mit Datenobjekten (NICHT JSON) hinweisen kann, wäre ich begeistert. Doppelt begeistert, wenn auch ng-init verwendet wird.
Code-Sushi

Ich verwende einfache Optionen, aber im Controller scheint der Wert der ausgewählten Dropdown-Liste nicht angezeigt zu werden. Beispiel: Ich habe versucht, alert ($ scope.sortorder.value); und alert ($ scope.sortorder); beides gibt undefiniert. Wie erhalte ich hier den ausgewählten Wert?
Maverick Riz

Vielen Dank dafür. Ich wollte gerade ein völlig nutzloses Objekt in den Controller schreiben, das ich nicht brauchte. Ich brauchte nur eine einfache Auswahl. Nochmals vielen Dank.
Muhammad bin Yusrat

22

Ähnliches passierte auch mir und wurde durch ein Upgrade auf Winkel 1.5 verursacht. ng-initscheint in neueren Versionen von Angular nach Typ analysiert zu werden . In älteren Angular ng-init="myModelName=600"würde eine Option mit dem Wert "600" zugeordnet, dh <option value="600">First</option>in Angular 1.5 wird dies nicht gefunden, da zu erwarten scheint, dass eine Option mit dem Wert 600 gefunden wird <option value=600>First</option>. Angular würde dann ein zufälliges erstes Element einfügen:

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

Winkel <1.2.x

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

Winkel> 1,2

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

1
Vielen Dank! In meinem Fall kann ich ng-init nicht verwenden (kein Standardwert), also habe ich mein Modell in einen String umgewandelt und es hat funktioniert!
Rodrigo Graça

Sehr nützlich für mein Problem mit der Anwendungsproduktion. Danke @Nabil Boag
Venki

3
Dies funktioniert zwar, aber die bessere Option ist die Verwendung ng-value="600"in der optionanstelle von value. Es wird es zu einer Zahl analysieren und Sie müssen Ihre Werte nicht wie jetzt konvertieren :)
Max

@Max Ich habe viele hochwertige Antworten ausprobiert, aber keine hat funktioniert, bis ich deine gefunden habe. Vielen Dank.
Andrew

21

Unter den zahlreichen Antworten hier dachte ich, ich würde die für mich funktionierende Lösung erneut veröffentlichen und alle folgenden Bedingungen erfüllen:

  • einen Platzhalter / eine Eingabeaufforderung bereitgestellt, wenn das ng-Modell falsch ist (z. B. "--select region--" w. value="")
  • Wenn der Wert des ng-Modells falsch ist und der Benutzer das Dropdown-Menü "Optionen" öffnet, wird der Platzhalter ausgewählt (bei anderen hier genannten Lösungen wird die erste Option als ausgewählt angezeigt, was irreführend sein kann).
  • Ermöglichen Sie dem Benutzer, die Auswahl eines gültigen Werts aufzuheben , indem Sie im Wesentlichen den falschen Wert / Standardwert erneut auswählen

Geben Sie hier die Bildbeschreibung ein

Code

<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

Original-Fragen und Antworten - https://stackoverflow.com/a/32880941/1121919


Meinst du, wenn der Standard ist <option ng-selected="true" value="null">?
Jusopi

Ich meine, wenn der Wert des ng-Modells auf Null gesetzt ist, wird eine winkelige und leere Option auf der Auswahl erstellt
Flezcano

16

Eine schnelle Lösung:

select option:empty { display:none }

Hoffe es hilft jemandem. Im Idealfall sollte die ausgewählte Antwort der Ansatz sein. Sollte dies jedoch nicht möglich sein, sollte dies als Patch funktionieren.


2
Nach meinen Tests funktioniert dies nur in Chrome (zusätzlich zu Chrome) und Firefox. IE und Safari brechen. Ich weiß nichts über Oper und andere Edge-Browser. In beiden Fällen ist dies leider keine gute Lösung.
Dudewad

wo sollen wir das in html vor dem ende von <select> oder sonst in js
H Varma

1
@HVarma Es ist eine CSS-Regel. Platzieren Sie es im Stylesheet oder im <style> -Tag
KK

@KK stackoverflow.com/questions/48355599/… Können Sie dies bitte überprüfen?
Sudarshan Kalebere

14

Ja, ng-model erstellt einen leeren Optionswert, wenn die Eigenschaft ng-model undefiniert ist. Wir können dies vermeiden, wenn wir dem ng-Modell ein Objekt zuweisen

Beispiel

Winkelcodierung

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

Wichtige Notiz:

Weisen Sie dem ng-Modell ein Array-Objekt wie $ scope.collections [0] oder $ scope.collections [1] zu. Verwenden Sie keine Objekteigenschaften. Wenn Sie mithilfe der Rückruffunktion einen ausgewählten Optionswert vom Server erhalten, weisen Sie dem ng-Modell ein Objekt zu

HINWEIS aus dem Angular-Dokument

Hinweis: ngModel vergleicht nach Referenz und nicht nach Wert. Dies ist wichtig, wenn Sie an ein Array von Objekten binden. siehe ein Beispiel http://jsfiddle.net/qWzTb/

Ich habe es oft versucht, endlich habe ich es gefunden.


8

Obwohl die Antworten von @ pkozlowski.opensource und @ Mark korrekt sind, möchte ich meine leicht modifizierte Version freigeben, in der ich immer das erste Element in der Liste auswähle, unabhängig von dessen Wert:

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

4

Ich verwende Angular 1.4x und habe dieses Beispiel gefunden. Daher habe ich ng-init verwendet, um den Anfangswert in der Auswahl festzulegen:

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

3


Ich stand vor dem gleichen Problem. Wenn Sie ein Winkelformular mit normalem Beitrag veröffentlichen, tritt dieses Problem auf, da Sie mit dem Winkel keine Werte für die Optionen in der von Ihnen verwendeten Weise festlegen können. Wenn Sie den Wert "form.type" erhalten, finden Sie den richtigen Wert. Sie müssen das eckige Objekt selbst posten, nicht den Formularpfosten.


3

Eine einfache Lösung besteht darin, eine Option mit einem leeren Wert festzulegen. ""Ich habe festgestellt, dass dadurch die zusätzliche undefinierte Option entfällt.


5
Doenst work @ 1.4.3, Es fügt nur 2 leere Optionen zum Formular hinzu
Denny Mueller

3

Ok, eigentlich ist die Antwort ganz einfach: Wenn es eine Option gibt, die Angular nicht erkennt, enthält sie eine langweilige. Was Sie falsch machen, ist, wenn Sie ng-options verwenden, liest es beispielsweise ein Objekt[{ id: 10, name: test }, { id: 11, name: test2 }] right?

Dies ist, was Ihr Modellwert sein muss, um ihn als gleich zu bewerten. Angenommen, Sie möchten, dass der ausgewählte Wert 10 ist. Sie müssen Ihr Modell auf einen Wert wie { id: 10, name: test }10 einstellen, daher wird dieser Papierkorb NICHT erstellt.

Hoffe es hilft allen zu verstehen, ich hatte es schwer zu versuchen :)


2

Diese Lösung funktioniert bei mir:

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

Eine Ablehnung könnte daran liegen, dass das Anwenden von CSS auf Optionselemente nicht in allen Browsern funktioniert.
Kafoso

Ich habe es gerade auf Chrome, FireFox, Safari und Edge getestet - alles funktioniert.
MMM

@MMM "Alle Browser" enthält IE. Viele Benutzer stecken immer noch mit IE 10 und 11 fest, und das ist wahrscheinlich der Grund, warum die Abwertung stattgefunden hat. Chrome, fF, Saf und Edge sind nicht "alle Browser".
PKD

1

Das hat bei mir funktioniert

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

Fügt einfach die Option in die Liste ein und lässt leider den leeren Raum.
AMontpetit

1

Das funktioniert einwandfrei

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

Die Art und Weise, wie es funktioniert, ist, dass dies die erste Option darstellt, die angezeigt wird, bevor etwas ausgewählt wird, und display:nonediese aus der Dropdown-Liste entfernt, damit Sie dies tun können, wenn Sie möchten

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

und dies gibt Ihnen das select and optionvor der Auswahl, aber sobald es ausgewählt ist, verschwindet es und es wird nicht in der Dropdown-Liste angezeigt.


Eigentlich beantwortest du die Frage selbst nicht, schlimmer noch, du versteckst nur das Element.
Marco

0

Versuchen Sie dies in Ihrem Controller in der gleichen Reihenfolge:

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

Ich habe Ihre Methode ausprobiert, aber leider konnte ich sie nicht zum Laufen bringen. Können Sie sich diese Geige ansehen? jsfiddle.net/5PdaX
Aniket Sinha

0

Hier ist das Update:

für ein Beispiel Daten wie:

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

Die Auswahloption sollte folgendermaßen aussehen: -

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

Wenn wir value.listCountals schreiben value.listName, wird der Text automatisch ausgefüllt value.listName, der Wert der ausgewählten Option ist jedochvalue.listCount obwohl die Werte my zeigen normal 0,1,2 .. und so weiter !!!

In meinem Fall financeRef.financeLimitgreift der tatsächlich nach dem value.listCountund ich kann meine Manipulation im Controller dynamisch durchführen.


0

Ich möchte hinzufügen, dass, wenn der Anfangswert von einer Bindung eines übergeordneten Elements oder einer 1.5-Komponente stammt, sicherstellen muss, dass der richtige Typ übergeben wird. Bei Verwendung@ in der Bindung ist die übergebene Variable eine Zeichenfolge, und wenn die Optionen z. Ganzzahlen, dann wird die leere Option angezeigt.

Analysieren Sie den Wert in init entweder richtig oder binden Sie ihn mit <und nicht @(weniger für die Leistung empfohlen, sofern nicht erforderlich).


0

Einfache Lösung

<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

Eine Grind-Lösung mit jQuery, wenn Sie nicht die Kontrolle über die Optionen haben

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();
}

Pascal, jemand hat dich herabgestimmt, weil dies eine jQuery-Lösung ist, nicht AngularJs
Mawg sagt, Monica am

Die Frage wird gestellt, um mehr von Angular herauszufinden ...: - /
Sahu V Kumar

0

Wenn Sie dieses Modell mit ng-init lösen, um dieses Problem zu lösen:

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

0

Ich hatte das gleiche Problem, ich (entferntes "ng-Modell") änderte dies:

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

dazu:

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

Jetzt funktioniert es, aber in meinem Fall wurde der Bereich von ng.controller gelöscht. Überprüfen Sie, ob Sie nicht dasselbe getan haben.



0

Das einzige , was für mich gearbeitet wird mit track byin ng-options, wie folgt aus :

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


wenn ich diese ng-optionbekommt letzten Wert von Array , das ich Sollwert soll von optionden select. Es wurde nicht gelöst :(
rufatZZ

0

Lesen Sie das Beispiel aus der AngularJS-Dokumentation, um diese Probleme zu beheben.

  1. Gehen Sie zu dieser Dokumentation Link hier
  2. Suchen Sie ' Bindungsauswahl über ngModel-Analyse / Formatierung an einen Wert ohne Zeichenfolge '.
  3. Dort können Sie sehen, dass die Direktive ' convertToNumber ' das Problem löst.

Für mich geht das. Kann auch sehen, wie es hier funktioniert


0

Wir können CSS verwenden, um die erste Option auszublenden. In IE 10, 11 funktioniert dies jedoch nicht. Der beste Weg ist, das Element mit Jquery zu entfernen. Diese Lösung funktioniert für große Browser, die in Chrome und IE10, 11 getestet wurden

Auch wenn Sie Angular verwenden, funktioniert die Verwendung von setTimeout manchmal

$scope.RemoveFirstOptionElement = function (element) {
    setTimeout(function () {
        $(element.children()[0]).remove();
    }, 0);
};
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.