web-dev-qa-db-fra.com

AngularJS - attribut de valeur pour select

Les données JSON source sont:

[
  {"name":"Alabama","code":"AL"},
  {"name":"Alaska","code":"AK"},
  {"name":"American Samoa","code":"AS"},
  ...
]

J'essaie

ng-options="i.code as i.name for i in regions"

mais je reçois:

<option value="?" selected="selected"></option>
<option value="0">Alabama</option>
<option value="1">Alaska</option>
<option value="2">American Samoa</option>

pendant que je m'attends à recevoir:

<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AS">American Samoa</option>

Alors, comment obtenir des attributs de valeur et se débarrasser de "?" article?

En passant, si je définis les champs $ scope.regions sur un JSON statique au lieu de AJAX), l'élément vide disparaît.

72
Paul

Ce que vous avez essayé en premier devrait fonctionner, mais le code HTML n’est pas ce à quoi nous nous attendions. J'ai ajouté une option pour gérer le cas initial "aucun élément sélectionné":

<select ng-options="region.code as region.name for region in regions" ng-model="region">
   <option style="display:none" value="">select a region</option>
</select>
<br>selected: {{region}}

Ce qui précède génère ce code HTML:

<select ng-options="..." ng-model="region" class="...">
   <option style="display:none" value class>select a region</option>
   <option value="0">Alabama</option>
   <option value="1">Alaska</option>
   <option value="2">American Samoa</option>
</select>

violon

Même si Angular utilise des entiers numériques pour la valeur, le modèle (c'est-à-dire $ scope.region) sera défini sur AL, AK ou AS, comme vous le souhaitez. (La valeur numérique est utilisée par Angular pour rechercher l'entrée de tableau correcte lorsqu'une option est sélectionnée dans la liste.)

Cela peut être déroutant lorsque vous apprenez pour la première fois comment Angular applique sa directive "select".

74
Mark Rajcok

Vous ne pouvez pas vraiment faire cela si vous ne les construisez pas vous-même.

<select ng-model="foo">
   <option ng-repeat="item in items" value="{{item.code}}">{{item.name}}</option>
</select>

MAIS ... ça n'en vaut probablement pas la peine. Il est préférable de laisser la fonction telle que conçue et de laisser Angular gérer les rouages ​​internes. Angular utilise l’index de cette façon afin que vous puissiez réellement utiliser un objet entier en tant que Vous pouvez donc utiliser une liaison déroulante pour sélectionner une valeur entière plutôt que simplement une chaîne, ce qui est assez impressionnant:

<select ng-model="foo" ng-options="item as item.name for item in items"></select>

{{foo | json}}
26
Ben Lesh

Si vous utilisez le track by option, l’attribut value est correctement écrit, par exemple:

<div ng-init="a = [{label: 'one', value: 15}, {label: 'two', value: 20}]">
    <select ng-model="foo" ng-options="x for x in a track by x.value"/>
</div>

produit:

<select>
    <option value="" selected="selected"></option>
    <option value="15">one</option>
    <option value="20">two</option>
</select>
21
Joscha

Si le modèle spécifié pour la liste déroulante n'existe pas, alors angular générera un élément d'options vide. Vous devrez donc spécifier explicitement le modèle de la sélection de la manière suivante:

<select ng-model="regions[index]" ng-options="....">

Reportez-vous à ce qui suit comme il a été répondu auparavant:

Pourquoi AngularJS inclut-il une option vide dans select? et ceci violon

Mise à jour: Essayez ceci à la place:

<select ng-model="regions[index].code" ng-options="i.code as i.name for i in regions">
</select>

or

<select ng-model="regions[2]" ng-options="r.name for r in regions">
</select>

Notez qu'il n'y a pas d'élément d'options vide dans la sélection.

7
msyed

Vous pouvez modifier votre modèle pour ressembler à ceci:

$scope.options = {
    "AL" : "Alabama",
    "AK" : "Alaska",
    "AS" : "American Samoa"
  };

Puis utiliser

<select ng-options="k as v for (k,v) in options"></select>
5
Olivier.Roger

Il apparaît qu'il n'est pas possible d'utiliser réellement la "valeur" d'une sélection de manière significative en tant qu'élément de formulaire HTML normal et de la raccorder également à Angular de la manière approuvée avec ng-options. En guise de compromis, je devais mettre une entrée cachée à côté de ma sélection et la faire suivre le même modèle que ma sélection, comme ceci (toutes très simplifiées du code de production réel par souci de brièveté):

HTML:

<select ng-model="profile" ng-options="o.id as o.name for o in profiles" name="something_i_dont_care_about">
</select>
<input name="profile_id" type="text" style="margin-left:-10000px;" ng-model="profile"/>

Javascript:

App.controller('ConnectCtrl',function ConnectCtrl($scope) {
$scope.profiles = [{id:'xyz', name:'a profile'},{id:'abc', name:'another profile'}];
$scope.profile = -1;
}

Ensuite, dans mon code côté serveur, je viens de chercher params[:profile_id] (il s’agissait d’une application Rails app, mais le même principe s’applique partout). Comme les entrées masquées suivent le même modèle que le modèle sélectionné, elles restent synchronisées automatiquement (aucun javascript supplémentaire n'est nécessaire ). C’est la partie cool d’Anger. Elle compense presque ce qu’elle fait à l’attribut value en tant qu’effet secondaire.

Fait intéressant, j'ai trouvé que cette technique ne fonctionnait qu'avec des balises d'entrée non masquées (c'est pourquoi j'ai dû utiliser la marge-gauche: -10000px; astuce pour déplacer l'entrée hors de la page). Ces deux variantes n'ont pas fonctionné:

<input name="profile_id" type="text" style="display:none;" ng-model="profile"/>

et

<input name="profile_id" type="hidden" ng-model="profile"/>

Je sens que cela doit signifier que je manque quelque chose. Cela semble trop bizarre pour que ce soit un problème avec Angular.

4
Tim Cull

vous pouvez utiliser

state.name for state in states track by state.code

Où états dans le tableau JSON, état est le nom de la variable pour chaque objet du tableau.

J'espère que cela t'aides

1
lazell