web-dev-qa-db-fra.com

Angular ajoute des options étranges dans l'élément select lors de la définition de la valeur du modèle

J'ai un élément select défini comme tel:

<select name="country_id" id="country_id" required="required" ng-model="newAddressForm.country_id">
    <option value="">Select Country</option>
    <option ng-repeat="country in countries" value="{{country.id}}">{{country.name}}</option>
</select>

Tout fonctionne bien lorsque je ne mets aucune valeur dans la directive qui contient cet élément select. Mais quand je fais quelque chose comme newAddressForm.country_id = 98, Au lieu de sélectionner l'option avec la valeur 98, Angular en injecte un nouveau en haut de l'élément select, comme ceci:

<option value="? string:98 ?"></option>

Ce qui donne? De quel type de format s'agit-il et pourquoi cela se produit-il? Notez que si je fais une console.log(newAddressForm.country_id) dans la directive, j'obtiens un "98" Normal, c'est juste bizarre dans le HTML généré.

Edit: Mise à jour de la situation. Passé à l'utilisation de ng-select, Mais le problème persiste.

L'élément bizarre n'apparaît plus, MAIS, il y a maintenant un autre élément en haut, celui qui n'a qu'un point d'interrogation ? Comme valeur, et pas d'étiquette.

C'est, d'après ce que j'ai rassemblé, l'option "none selected" D'Angular. Je ne comprends toujours pas pourquoi il ne sélectionnera pas l'option que je lui dis de sélectionner, cependant.

Faire newAddressForm.country_id = 98 Ne donne toujours aucun résultat. Pourquoi donc?

44
Swader

Angular ne définit pas la valeur d'un élément select sur les valeurs réelles de votre tableau et effectue certaines opérations internes pour gérer la liaison de portée. Voir le premier commentaire de Mark Rajcok sur ce lien:

https://docs.angularjs.org/api/ng/directive/select#overview

Lorsque l'utilisateur sélectionne l'une des options, Angular utilise l'index (ou la clé) pour rechercher la valeur dans le tableau (ou l'objet) - cette valeur recherchée est ce que le modèle est défini (Donc, le modèle n'est pas défini sur la valeur que vous voyez dans le HTML! Cela provoque beaucoup de confusion.)

Je ne suis pas tout à fait sûr d'utiliser un ng-repeat est la meilleure option.

16
lucuma

Utilisation de la syntaxe suivante avec ng-options a résolu ce problème pour moi:

<select name="country_id" id="country_id" required="required" ng-model="newAddressForm.country_id" ng-options="country.id as country.name for country in countries">
  <option value="">Select Country</option>
</select>
20
jessedvrs

Si vos valeurs sont des nombres entiers, vous devez utiliser "" même si ce ne sont pas des chaînes, cette raison simple est exactement la raison pour laquelle vous obtenez une option avec un point d'interrogation comme valeur.

Vous ne devriez pas utiliser ceci:

{ value: 0, name: "Pendiente" },
{ value: 1, name: "Em andamento" },
{ value: 2, name: "Erro" },
{ value: 3, name: "Enviar email" },
{ value: 4, name: "Enviado" }

C'est le bon chemin:

{ value: "0", name: "Pendiente" },
{ value: "1", name: "Em andamento" },
{ value: "2", name: "Erro" },
{ value: "3", name: "Enviar email" },
{ value: "4", name: "Enviado" }

Si vous avez au moins un enregistrement qui n'utilise pas "", vous obtiendrez ceci? valeur d'option.

2
Martin

Lorsque vous affectez une valeur à un élément select, AngularJS recherche la valeur fournie dans l'attribut value des balises d'option de cet élément select. Mais le hic est, AngularJS fait une comparaison basée sur le type. Donc, si les valeurs dans les balises d'options sont des chaînes (ce qui est généralement le cas) et que la variable que vous liez à l'aide de ng-model est un nombre, AngularJS ne parvient pas à trouver l'élément d'option correspondant et, par conséquent, crée son propre élément comme celui-ci -

<option value="? integer:10 ?"></option>

La solution consiste, tout en se liant, à la convertir au type approprié.

Dans ce cas, la solution serait de lier un entier

<select name="country_id" id="country_id" required="required" ng-model="parseInt(newAddressForm.country_id)">
<option value="">Select Country</option>
<option ng-repeat="country in countries" value="{{country.id}}">{{country.name}}</option>
</select>

Si les valeurs sont définies comme des chaînes, l'astuce serait d'utiliser

<select ... ng-model="newAddressForm.country_id.toString()" >
1
Pratik Kapasi

Je rencontrais ce même problème plus tôt ce soir, où j'ai vu une option de sélection apparaître comme la première de ma liste même si je ne l'avais pas explicitement créée. Je remplissais une liste d'options de sélection dans mon contrôleur et j'utilisais la même syntaxe ng-options mentionnée ci-dessus par jessedvrs (sauf que j'insérais également l'option par défaut "sélectionner une option" dans le contrôleur plutôt que de la marquer dans le HTML comme il était).

Pour une raison quelconque, la liste de sélection afficherait toujours une option supplémentaire à l'index zéro avec une valeur de "?", Mais lorsque j'ai changé la façon dont j'ai rempli mon option par défaut dans le contrôleur, ce problème a disparu. Je remplissais les options de sélection en faisant un appel API, en les remplissant à l'intérieur d'une promesse. J'ai fait l'erreur de remplir également mon option par défaut "sélectionner une option" comme la première chose que j'ai faite dans cette promesse, mais quand je l'ai fait à la place extérieur de la promesse (avant de faire l'appel API) , les options de sélection ont rempli la façon dont je les ai déclinées.

Je pense que l'option jessedvrs est une solution au problème (définir l'option par défaut dans le balisage HTML), mais si vous préférez remplir vos options en javascript à la place, je suggérerais de toujours définir l'option par défaut avant de faire des appels à une API ou des processus qui peuvent encore être en cours d'exécution pendant le rendu du code HTML.

1
Developer Dave

Tout en poussant les données sur la variable de portée, nous pouvons utiliser le code suivant

$scope.enquiryLocationRow.Push({'location': EnqLocation.location, 'state_id': Number(EnqLocation.state_id), 'country_id': Number(EnqLocation.country_id)});

cela a résolu mon problème

0
Manoj Atakare

utilisez "track by 'value'" à la fin de vos options ng: D

comme l'exemple ci-dessous:

ng-options = "country.id as country.name pour le pays dans les pays suivi par country.id"

0
Renan.