web-dev-qa-db-fra.com

Pourquoi AngularJS inclut-il une option vide dans select?

Je travaille avec AngularJS depuis quelques semaines et ce qui me dérange vraiment, c’est que même après avoir essayé toutes les permutations ou la configuration définie dans la spécification sur http://docs.angularjs.org /api/ng.directive:select , je reçois toujours une option vide en tant que premier enfant de l'élément select.

Voici le jade:

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

Voici le contrôleur:

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

Enfin, voici le code HTML généré:

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

Que dois-je faire pour m'en débarrasser?

P.S .: Cela fonctionne aussi sans cela, mais ça a l'air bizarre si vous utilisez select2 sans sélection multiple.

635
Sudhanshu

Le option vide est généré lorsqu'une valeur référencée par ng-model n'existe pas dans un ensemble d'options transmises à ng-options. Cela empêche la sélection accidentelle de modèles: AngularJS peut voir que le modèle initial est indéfini ou non dans l'ensemble des options et ne veut pas décider seul de la valeur du modèle.

Si vous souhaitez vous débarrasser de l'option vide, sélectionnez simplement une valeur initiale dans votre contrôleur, par exemple:

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

Voici le jsFiddle: http://jsfiddle.net/MTfRD/3/

En bref: l'option vide signifie qu'aucun modèle valide n'est sélectionné (par valide, je veux dire: parmi l'ensemble des options). Vous devez sélectionner une valeur de modèle valide pour vous débarrasser de cette option vide.

635

Si vous voulez une valeur initiale, voir la réponse de @ pkozlowski.opensource, qui FYI peut également être implémentée dans la vue (plutôt que dans le contrôleur) à l'aide de 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>

Si vous ne voulez pas de valeur initiale, "un seul élément codé en dur, avec la valeur définie comme chaîne vide, peut être imbriqué dans l'élément. Cet élément représentera alors l'option null ou" non sélectionné "":

<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>
228
Mark Rajcok

angulaire <1.4

Pour tous ceux qui considèrent "null" comme une valeur valide pour l’une des options (imaginez que "null" soit la valeur de l’un des éléments de typeOptions dans l'exemple ci-dessous), j'ai trouvé que le moyen le plus simple de s'assurer que l'option automatiquement ajoutée est masquée est d'utiliser ng-if.

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

Pourquoi ng-if et pas ng-hide? Parce que vous voulez que les sélecteurs CSS qui ciblent la première option ci-dessus sélectionnent l'option "réelle", et non celle qui est cachée. Cela devient utile lorsque vous utilisez protractor pour tester e2e et (quelle que soit la raison) vous utilisez by.css () pour cibler les options sélectionnées.

angulaire> = 1,4

En raison du refactoring des directives select et options, utiliser ng-if n'est plus une option viable, vous devez donc vous tourner vers ng-show="false" pour le faire fonctionner à nouveau.

120
WTK

Peut-être utile pour quelqu'un:

Si vous voulez utiliser des options simples au lieu de ng-options, vous pouvez faire comme ci-dessous:

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

Définissez le modèle en ligne. Utilisez ng-init pour vous débarrasser de l'option vide

36
Abraham Jagadeesh

Quelque chose de semblable m’arrivait à moi aussi et qui était causé par une mise à niveau vers angular 1.5 .ng-init semble être analysé pour type dans les nouvelles versions de Angular. Dans les versions plus anciennes Angular ng-init="myModelName=600" correspondrait à une option de valeur "600", c.-à-d. <option value="600">First</option>, mais dans Angular 1.5, elle ne le trouverait pas car elle semble s'attendre à trouver une option de valeur 600, c'est-à-dire <option value=600>First</option>. Angular insérerait alors un premier élément aléatoire:

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

angulaire <1.2.x

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

angulaire> 1.2

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

Parmi la multitude de réponses ici, je me suis dit que je republierais la solution qui fonctionnait pour moi et que je rencontrais toutes les conditions suivantes:

  • a fourni un espace réservé//Invite lorsque le modèle ng est falsy (par exemple, "--select region--" w. value="")
  • lorsque la valeur de ng-model est falsy et que l'utilisateur ouvre la liste des options, l'espace réservé est sélectionné (les autres solutions mentionnées ici font apparaître la première option sélectionnée, ce qui peut induire en erreur).
  • permettre à l'utilisateur de désélectionner une valeur valide, en sélectionnant à nouveau la valeur falsy /default

enter image description here

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

questions et réponses originales - https://stackoverflow.com/a/32880941/1121919

20
jusopi

Une solution rapide:

select option:empty { display:none }

J'espère que ça aide quelqu'un. Idéalement, la réponse choisie devrait être l'approche, mais si dans le cas où cela ne serait pas possible, alors fonctionnerait comme un patch.

16
K K

Oui, ng-model créera une valeur d'option vide, lorsque la propriété ng-model ne sera pas définie. Nous pouvons éviter cela si nous affectons un objet à ng-model

Exemple

codage angulaire

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

Note importante:

Attribuez un objet de tableau comme $ scope.collections [0] ou $ scope.collections [1] à ng-model, n'utilisez pas les propriétés d'objet. si vous obtenez une valeur d'option de sélection du serveur, en utilisant la fonction de rappel, affectez l'objet à ng-model

NOTE du Angular document

Remarque: ngModel compare par référence et non par valeur. Ceci est important lors de la liaison à un tableau d'objets. voir un exemple http://jsfiddle.net/qWzTb/

j'ai essayé beaucoup de fois finalement je l'ai trouvé.

14
Kanagaraj Vadivel

Bien que les réponses de @ pkozlowski.opensource et de @ Mark soient correctes, j'aimerais partager ma version légèrement modifiée dans laquelle je sélectionne toujours le premier élément de la liste, quelle que soit sa valeur:

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

J'utilise Angular 1.4x et j'ai trouvé cet exemple. J'ai donc utilisé ng-init pour définir la valeur initiale dans la sélection:

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

Ok, en fait, la réponse est simple: quand il y a une option non reconnue par Angular, elle en inclut une ennuyeuse. Ce que vous faites mal, c’est que lorsque vous utilisez ng-options, il lit un objet, par exemple [{ id: 10, name: test }, { id: 11, name: test2 }] right?

C’est la valeur que votre modèle doit avoir pour l’évaluer en tant qu’égale. Par exemple, si vous voulez que la valeur sélectionnée soit 10, vous devez lui attribuer une valeur telle que { id: 10, name: test } pour en sélectionner 10, donc elle ne créera PAS cette corbeille. .

J'espère que ça aide tout le monde à comprendre, j'ai eu du mal à essayer :)

3
Marco


J'ai été confronté au même problème. Si vous postez un formulaire angular avec une publication normale, vous serez confronté à ce problème, car angular ne vous permettra pas de définir des valeurs pour les options de la manière que vous avez utilisée. Si vous obtenez la valeur "form.type", vous trouverez la bonne valeur. Vous devez poster l'objet angular lui-même et non le formulaire.

3
Jitu

Une solution simple consiste à définir une option avec une valeur vide. "" J'ai constaté que cela élimine l'option supplémentaire non définie.

2
kgrondell

Cela fonctionne parfaitement bien

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

la façon dont cela fonctionne est que cela donne la première option à afficher avant de sélectionner quelque chose et que le display:none le supprime du menu déroulant. Si vous le souhaitez, vous pouvez le faire.

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

et cela vous donnera le select and option avant la sélection mais une fois sélectionné, il disparaîtra et il n'apparaîtra pas dans le menu déroulant.

1
David Genger

Cette solution fonctionne pour moi:

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

Cela a fonctionné pour moi

<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>
1
Nayas Subramanian

Nous pouvons utiliser CSS pour masquer la première option, mais cela ne fonctionnera pas dans IE 10, 11. Le meilleur moyen est de supprimer l'élément à l'aide de Jquery. Cette solution fonctionne pour les principaux navigateurs testés sous chrome et IE10, 11.

De même, si vous utilisez angular, vous pouvez parfois utiliser setTimeout

$scope.RemoveFirstOptionElement = function (element) {
    setTimeout(function () {
        $(element.children()[0]).remove();
    }, 0);
};
0
Ashok Kumar

Une solution Grind avec jQuery lorsque vous n'avez pas le contrôle des options

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

Si vous utilisez ng-init votre modèle pour résoudre ce problème:

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

Bonjour, j’avais quelques références mobiles jQUery et je les ai supprimées. Avec jQuery mobile, aucune des corrections ci-dessus ne fonctionnait pour moi. (C'est génial si quelqu'un peut expliquer le conflit entre jQuery Mobile et Angular JS)

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

Voici le correctif:

pour un exemple de données comme:

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

L'option de sélection devrait être comme ceci: -

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

Le point étant lorsque nous écrivons value.listCount en tant que value.listName, il remplit automatiquement le texte dans value.listName mais la valeur de l'option sélectionnée est value.listCount bien que les valeurs my affichent la valeur 0, 1,2 .. et ainsi de suite !!!

Dans mon cas, le financeRef.financeLimit récupère réellement le value.listCount et je peux effectuer ma manipulation de manière dynamique dans le contrôleur.

0
lisapanda

Essayez celui-ci dans votre contrôleur, dans le même ordre:

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

Solution simple

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

La seule chose qui a fonctionné pour moi est d'utiliser track by dans ng-options, comme ceci:

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

j'ai eu le même problème, j'ai (enlevé "ng-model") changé ceci:

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

pour ça:

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

maintenant cela fonctionne, mais dans mon cas, c’est parce que j’ai supprimé cette portée de ng.controller, vérifiez si vous n’avez pas fait de même.

0
Kuza Grave

J'aimerais ajouter que si la valeur initiale provient d'une liaison d'un élément parent ou d'un composant 1.5, assurez-vous que le type approprié est passé. Si vous utilisez @ dans la liaison, la variable transmise sera chaîne et si les options sont eg. entiers alors l'option vide apparaîtra.

Soit analyser correctement la valeur dans init, ou bien lier avec < et non pas @ (moins recommandé pour les performances sauf si nécessaire).

0
Wtower

Reportez-vous à l'exemple de la documentation d'angularjs pour savoir comment résoudre ces problèmes.

  1. Allez à ce lien de documentation ici
  2. Find ' Binding sélectionne une valeur non-chaîne via l'analyse/le formatage de ngModel '
  3. Vous pouvez y voir une directive appelée ' convertToNumber ' qui résout le problème.

Ça marche pour moi. Peut aussi voir comment ça marche ici

0
ihsanberahim