Voici ce qui semble déranger beaucoup de gens (y compris moi).
Lorsque vous utilisez la directive ng-options
dans AngularJS pour renseigner les options d'une balise <select>
, je ne peux pas comprendre comment définir la valeur d'une option. La documentation à ce sujet n’est vraiment pas claire - du moins pour un simple fou comme moi.
Je peux facilement définir le texte d'une option comme ceci:
ng-options="select p.text for p in resultOptions"
Quand resultOptions
est par exemple:
[
{
"value": 1,
"text": "1st"
},
{
"value": 2,
"text": "2nd"
}
]
Il devrait être (et est probablement) la chose la plus simple pour définir les valeurs des options, mais jusqu'à présent, je ne les comprends pas.
Voir ngOptions
ngOptions (facultatif) - {
comprehension_expression=
} - sous l'une des formes suivantes:Pour les sources de données de tableaux :
label for value in array
select as label for value in array
label group by group for value in array
select as label group by group for value in array track by trackexpr
Pour les sources de données objet :label for (key , value) in object
select as label for (key , value) in object
label group by group for (key, value) in object
select as label group by group for (key, value) in object
Dans votre cas, il devrait être
array = [{ "value": 1, "text": "1st" }, { "value": 2, "text": "2nd" }];
<select ng-options="obj.value as obj.text for obj in array"></select>
Avec les mises à jour sur AngularJS, il est maintenant possible de définir la valeur réelle de l'attribut value
de l'élément select
avec l'expression track by
.
<select ng-options="obj.text for obj in array track by obj.value">
</select>
Pour toutes les personnes qui ont du mal à se souvenir de cette forme de syntaxe: je conviens que ce n'est pas la syntaxe la plus facile ou la plus belle. Cette syntaxe est en quelque sorte une version étendue de la compréhension de liste de Python et, en sachant cela, elle m’aide à me souvenir de la syntaxe très facilement. C'est quelque chose comme ça:
Code Python:
my_list = [x**2 for x in [1, 2, 3, 4, 5]]
> [1, 4, 9, 16, 25]
# Let people to be a list of person instances
my_list2 = [person.name for person in people]
> my_list2 = ['Alice', 'Bob']
C'est en fait la même syntaxe que la première énumérée ci-dessus. Cependant, dans <select>
, nous devons généralement faire la différence entre la valeur réelle dans le code et le texte affiché (l'étiquette) dans un élément <select>
.
Comme, nous avons besoin de person.id
dans le code, mais nous ne voulons pas montrer le id
à l'utilisateur; nous voulons montrer son nom. De même, le person.name
du code ne nous intéresse pas. Vient ensuite le mot clé as
pour étiqueter les éléments. Alors ça devient comme ça:
person.id as person.name for person in people
Ou bien, au lieu de person.id
, nous pourrions avoir besoin de l'instance person
. Voir ci-dessous:
person as person.name for person in people
Pour les objets JavaScript, la même méthode s'applique également. Rappelez-vous simplement que les éléments de l'objet sont déconstruits avec (key, value)
paires.
Comment la valeur attribue-t-elle sa valeur:
Donc, dans votre cas, cela devrait être:
obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>
J'ai eu ce problème aussi. Je n'ai pas pu définir ma valeur dans ng-options. Chaque option générée était définie sur 0, 1, ..., n.
Pour bien faire les choses, j’ai fait quelque chose comme ça dans mes options:
<select ng-options="room.name for room in Rooms track by room.price">
<option value="">--Rooms--</option>
</select>
J'utilise "suivi par" pour définir toutes mes valeurs avec room.price
.
(Cet exemple est nul: parce que s'il y avait plus d'un prix égal, le code échouerait. ASSUREZ-VOUS donc d'avoir des valeurs différentes.)
$scope.Rooms = [
{ name: 'SALA01', price: 100 },
{ name: 'SALA02', price: 200 },
{ name: 'SALA03', price: 300 }
];
Je l'ai appris de l'article de blog Comment définir la valeur initiale sélectionnée d'un élément de sélection à l'aide de Angular.JS ng-options & track by.
Voir la vidéo. C'est une belle classe :)
Si vous souhaitez modifier la valeur de vos éléments option
car le formulaire sera éventuellement soumis au serveur, au lieu de le faire,
<select name="text" ng-model="text" ng-options="select p.text for p in resultOptions"></select>
Tu peux le faire:
<select ng-model="text" ng-options="select p.text for p in resultOptions"></select>
<input type="hidden" name="text" value="{{ text }}" />
La valeur attendue sera ensuite envoyée via le formulaire sous le nom correct.
Pour envoyer une valeur personnalisée appelée my_hero
au serveur à l'aide d'un formulaire normal, envoyez:
JSON:
"heroes": [
{"id":"iron", "label":"Iron Man Rocks!"},
{"id":"super", "label":"Superman Rocks!"}
]
HTML:
<select ng-model="hero" ng-options="obj.id as obj.label for obj in heroes"></select>
<input type="hidden" name="my_hero" value="{{hero}}" />
Le serveur recevra soit iron
ou super
en tant que valeur de my_hero
.
Ceci est similaire à la réponse de @neemzy , mais en spécifiant des données distinctes pour l'attribut value
.
Il semble que ng-options
soit compliqué à utiliser, voire frustrant, mais nous avons en réalité un problème d’architecture.
AngularJS sert de cadre MVC pour une application dynamique HTML + JavaScript. Bien que son composant (V) iew offre un "modèle" HTML, son objectif principal est de connecter les actions de l'utilisateur, via un contrôleur, aux modifications du modèle. Par conséquent le niveau d'abstraction approprié, à partir duquel travailler dans AngularJS, est qu'un élément select définit une valeur dans le modèle sur une valeur issue d'une requête .
ng-options
fournit le mot clé for
pour dicter le contenu de l'élément option c'est-à-dire p.text for p in resultOptions
.ng-options
fournit le mot clé as
pour spécifier la valeur fournie au modèle, comme dans k as v for (k,v) in objects
.La solution correcte de ce problème est donc de nature architecturale et implique de refactoriser votre code HTML afin que le (M) odel établisse la communication avec le serveur lorsque requis (au lieu du paramètre utilisateur soumettant un formulaire).
Si une page HTML de MVC entraîne une sur-ingénierie inutile pour le problème en question: , utilisez uniquement la partie HTML de la génération du composant iew d’AngularJS (V). Dans ce cas, suivez le même modèle que celui utilisé pour générer des éléments tels que les <li />
sous <ul />
et placez un ng-repeat sur un élément d'option:
<select name=“value”>
<option ng-repeat=“value in Model.Values” value=“{{value.value}}”>
{{value.text}}
</option>
</select>
Comme kludge , on peut toujours déplacer l'attribut name de l'élément select vers un élément d'entrée masqué:
<select ng-model=“selectedValue” ng-options=“value.text for value in Model.Values”>
</select>
<input type=“hidden” name=“value” value=“{{selectedValue}}” />
Tu peux le faire:
<select ng-model="model">
<option value="">Select</option>
<option ng-repeat="obj in array" value="{{obj.id}}">{{obj.name}}</option>
</select>
-- MISE À JOUR
Après quelques mises à jour, la solution de tilisateur ) de frm.adiputra est bien meilleure. Code:
obj = { '1': '1st', '2': '2nd' };
<select ng-options="k as v for (k,v) in obj"></select>
J'ai lutté avec ce problème pendant un certain temps aujourd'hui. J'ai lu la documentation d'AngularJS, cet article et d'autres ainsi que quelques blogs auxquels ils ont abouti. Ils m'ont tous aidé à comprendre les détails les plus fins, mais à la fin, cela semble être un sujet déroutant. Principalement à cause des nombreuses nuances syntaxiques de ng-options
.
En fin de compte, pour moi, il s'est agi de moins, c'est plus.
Étant donné une portée configurée comme suit:
//Data used to populate the dropdown list
$scope.list = [
{"FirmnessID":1,"Description":"Soft","Value":1},
{"FirmnessID":2,"Description":"Medium-Soft","Value":2},
{"FirmnessID":3,"Description":"Medium","Value":3},
{"FirmnessID":4,"Description":"Firm","Value":4},
{"FirmnessID":5,"Description":"Very Firm","Value":5}];
//A record or row of data that is to be save to our data store.
//FirmnessID is a foreign key to the list specified above.
$scope.rec = {
"id": 1,
"FirmnessID": 2
};
C'est tout ce dont j'avais besoin pour obtenir le résultat souhaité:
<select ng-model="rec.FirmnessID"
ng-options="g.FirmnessID as g.Description for g in list">
<option></option>
</select>
Remarquez que je n'ai pas utilisé track by
. En utilisant track by
l'élément sélectionné retournerait toujours l'objet correspondant au FirmnessID, plutôt que le FirmnessID lui-même. Cela répond maintenant à mes critères, à savoir qu'il doit renvoyer une valeur numérique plutôt que l'objet, et utiliser ng-options
pour améliorer les performances fournies en ne créant pas de nouvelle étendue pour chaque option générée.
De plus, j'avais besoin de la première ligne vierge, alors j'ai simplement ajouté un <option>
à l'élément <select>
.
Voici un Plunkr qui montre mon travail.
Au lieu d'utiliser la nouvelle fonctionnalité "piste par", vous pouvez simplement le faire avec un tableau si vous voulez que les valeurs soient les mêmes que le texte:
<select ng-options="v as v for (k,v) in Array/Obj"></select>
Notez la différence entre la syntaxe standard, qui transformera les valeurs en clés de l’objet/du tableau, et donc de 0,1,2, etc. pour un tableau:
<select ng-options"k as v for (k,v) in Array/Obj"></select>
k comme v devient v comme v.
J'ai découvert cela juste sur la base du bon sens en regardant la syntaxe. (k, v) est la déclaration qui divise le tableau/objet en paires clé-valeur.
Dans l'instruction 'k as v', k sera la valeur et v sera l'option de texte affichée à l'utilisateur. Je pense que "track by" est désordonné et excessif.
Cela convenait le mieux à tous les scénarios selon moi:
<select ng-model="mySelection.value">
<option ng-repeat="r in myList" value="{{r.Id}}" ng-selected="mySelection.value == r.Id">{{r.Name}}
</option>
</select>
où vous pouvez utiliser votre modèle pour lier les données. Vous obtiendrez la valeur que l'objet contiendra et la sélection par défaut en fonction de votre scénario.
C'est comment j'ai résolu ceci. J'ai suivi la sélection par valeur et défini la propriété de l'élément sélectionné sur le modèle dans mon code JavaScript.
Countries =
[
{
CountryId = 1, Code = 'USA', CountryName = 'United States of America'
},
{
CountryId = 2, Code = 'CAN', CountryName = 'Canada'
}
]
<select ng-model="vm.Enterprise.AdminCountry" ng-options="country.CountryName for country in vm.Countries track by country.CountryId">
vm
est mon contrôleur et le pays dans le contrôleur extrait du service est {CountryId =1, Code = 'USA', CountryName='United States of America'}
.
Lorsque j'ai sélectionné un autre pays dans le menu déroulant de sélection et que j'ai posté ma page avec "Enregistrer", le bon pays est lié.
La directive ng-options
ne définit pas l'attribut value sur les éléments <options>
pour les tableaux:
Utiliser limit.value as limit.text for limit in limits
signifie:
définir le label de
<option>
commelimit.text
enregistrez la valeurlimit.value
dans la sélectionng-model
Voir la question relative au débordement de pile Les options de rendu AngularJS n'affichent pas les valeurs.
<select ng-model="color" ng-options="(c.name+' '+c.shade) for c in colors"></select><br>
Un an après la question, je devais trouver une réponse à cette question, car aucune d’entre elles ne donnait la réponse, du moins pour moi.
Vous avez demandé comment sélectionner l'option, mais personne n'a dit que ces deux choses sont PAS identiques:
Si nous avons une option comme celle-ci:
$scope.options = [
{ label: 'one', value: 1 },
{ label: 'two', value: 2 }
];
Et nous essayons de définir une option par défaut comme celle-ci:
$scope.incorrectlySelected = { label: 'two', value: 2 };
Cela ne fonctionnera PAS, mais si vous essayez de sélectionner l'option comme ceci:
$scope.correctlySelected = $scope.options[1];
Cela va TRAVAILLER.
Même si ces deux objets ont les mêmes propriétés, AngularJS les considère comme DIFFÉRENTS car AngularJS compare par la référence .
Jetez un coup d'oeil au violon http://jsfiddle.net/qWzTb/ .
La bonne réponse à cette question a été fournie par l'utilisateur frm.adiputra , comme cela semble être actuellement le seul moyen de contrôler explicitement l'attribut value de les éléments d'option.
Cependant, je voulais simplement souligner que "sélectionner" n'est pas un mot clé dans ce contexte, mais simplement un espace réservé pour une expression. Veuillez vous référer à la liste suivante pour la définition de l'expression "select" ainsi que d'autres expressions pouvant être utilisées dans la directive ng-options.
L'utilisation de select telle qu'elle est décrite dans la question:
ng-options='select p.text for p in resultOptions'
est essentiellement faux.
Sur la base de la liste des expressions, il semble que trackexpr puisse être utilisé pour spécifier la valeur, lorsque les options sont données dans un tableau d'objets, mais été utilisé avec le groupement seulement.
De la documentation d'AngularJS sur les options-ng:
La sélection d'un élément dans ng-options peut être un peu délicate selon la manière dont vous définissez la source de données.
Après avoir lutté avec eux pendant un moment, j'ai fini par créer un échantillon avec les sources de données les plus courantes que j'utilise. Vous pouvez le trouver ici:
http://plnkr.co/edit/fGq2PM?p=preview
Maintenant, pour que ng-options fonctionne, voici quelques points à considérer:
key | label
. De nombreux exemples en ligne placent les objets en tant que "clé" et, si vous avez besoin d'informations provenant de l'objet, définissez-les de cette façon, sinon utilisez la propriété spécifique dont vous avez besoin en tant que clé. (ID, CODE, etc. Comme dans l'exemple plckr)La manière de définir la valeur du contrôle déroulant/sélectionné dépend de # 3,
$scope.dropdownmodel = $scope.user.state;
Si vous définissez l'objet comme clé, vous devez parcourir les options. Même l'attribution de l'objet ne définira pas l'élément de la manière sélectionnée, car elles auront des hashkeys différents, par exemple:
for (var i = 0, len = $scope.options.length; i < len; i++) {
if ($scope.options[i].id == savedValue) { // Your own property here:
console.log('Found target! ');
$scope.value = $scope.options[i];
break;
}
}
Vous pouvez remplacer savedValue pour la même propriété dans l'autre objet, $scope.myObject.myProperty
.
Pour moi la réponse de Bruno Gomes est la meilleure réponse.
Mais en réalité, vous n'avez pas à vous préoccuper de la définition de la propriété value des options select. AngularJS se chargera de cela. Laissez-moi vous expliquer en détail.
S'il vous plaît considérez ce violon
angular.module('mySettings', []).controller('appSettingsCtrl', function ($scope) {
$scope.timeFormatTemplates = [{
label: "Seconds",
value: 'ss'
}, {
label: "Minutes",
value: 'mm'
}, {
label: "Hours",
value: 'hh'
}];
$scope.inactivity_settings = {
status: false,
inactive_time: 60 * 5 * 3, // 15 min (default value), that is, 900 seconds
//time_format: 'ss', // Second (default value)
time_format: $scope.timeFormatTemplates[0], // Default seconds object
};
$scope.activity_settings = {
status: false,
active_time: 60 * 5 * 3, // 15 min (default value), that is, 900 seconds
//time_format: 'ss', // Second (default value)
time_format: $scope.timeFormatTemplates[0], // Default seconds object
};
$scope.changedTimeFormat = function (time_format) {
'use strict';
console.log('time changed');
console.log(time_format);
var newValue = time_format.value;
// do your update settings stuffs
}
});
Comme vous pouvez le voir dans la sortie violon, peu importe ce que vous choisissez pour les options de sélection, il s’agit de votre valeur personnalisée, ou de la valeur 0, 1, 2 générée automatiquement par AngularJS. autre bibliothèque pour accéder à la valeur de cette option et la manipuler en conséquence.
Veuillez utiliser piste par propriété pour différencier les valeurs et les libellés dans la zone de sélection.
S'il vous plaît essayez
<select ng-options="obj.text for obj in array track by obj.value"></select>
qui assignera des étiquettes avec du texte et une valeur avec une valeur (du tableau)
Vous pouvez utiliser ng-options pour obtenir une liaison de balise select aux membres value et display
En utilisant cette source de données
countries : [
{
"key": 1,
"name": "UAE"
},
{
"key": 2,
"name": "India"
},
{
"key": 3,
"name": "OMAN"
}
]
vous pouvez utiliser ce qui suit pour lier votre balise select à la valeur et au nom
<select name="text" ng-model="name" ng-options="c.key as c.name for c in countries"></select>
ça marche très bien
Pour un objet:
<select ng-model="mySelect" ng-options="key as value for (key, value) in object"></select>
Le tutoriel ANGULAR.JS: NG-SELECT ET NG-OPTIONS m'a aidé à résoudre le problème:
<select id="countryId"
class="form-control"
data-ng-model="entity.countryId"
ng-options="value.dataValue as value.dataText group by value.group for value in countries"></select>
C'est toujours pénible pour les développeurs avec ng-options. Par exemple: Obtenir une valeur sélectionnée vide/vide dans la balise select. Cela devient particulièrement fastidieux en particulier lorsque vous utilisez des objets JSON dans ng-options. Ici, j'ai fait quelques exercices à ce sujet.
Objectif: Itérer un tableau d'objets JSON via ng-option et définir le premier élément sélectionné.
Les données:
someNames = [{"id":"1", "someName":"xyz"}, {"id":"2", "someName":"abc"}]
Dans la balise select, je devais montrer xyz et abc, où xyz devait être sélectionné sans trop d'effort.
<pre class="default prettyprint prettyprinted" style=""><code>
<select class="form-control" name="test" style="width:160px" ng-options="name.someName for name in someNames" ng-model="testModel.test" ng-selected = "testModel.test = testModel.test || someNames[0]">
</select>
</code></pre>
Par exemple de code ci-dessus, vous pourriez sortir de cette exagération.
Un autre référence :
<select ng-model="output">
<option ng-repeat="(key,val) in dictionary" value="{{key}}">{{val}}</option>
</select>
Exécutez l'extrait de code et observez les variations. Voici une note pour une compréhension rapide
Exemple 1 (sélection d'objet): - ng-option="os.name for os in osList track by os.id"
. Ici track by os.id
est important & devrait être là et os.id as
ne devrait PAS avoir avant os.name
.
ng-model="my_os"
doit être défini sur un objet dont la clé est id comme my_os={id: 2}
.Exemple 2 (sélection de valeur): - ng-option="os.id as os.name for os in osList"
. Ici track by os.id
ne devrait PAS être là et os.id as
devrait être avant os.name
.
ng-model="my_os"
doit être défini sur une valeur telle que my_os= 2
L'extrait de code de repos va expliquer.
angular.module('app', []).controller('ctrl', function($scope, $timeout){
//************ EXAMPLE 1 *******************
$scope.osList =[
{ id: 1, name :'iOS'},
{ id: 2, name :'Android'},
{ id: 3, name :'Windows'}
]
$scope.my_os = {id: 2};
//************ EXAMPLE 2 *******************
$timeout(function(){
$scope.siteList = [
{ id: 1, name: 'Google'},
{ id: 2, name: 'Yahoo'},
{ id: 3, name: 'Bing'}
];
}, 1000);
$scope.my_site = 2;
$timeout(function(){
$scope.my_site = 3;
}, 2000);
})
fieldset{
margin-bottom: 40px;
}
strong{
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.10/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<!--//************ EXAMPLE 1 *******************-->
<fieldset>
<legend>Example 1 (Set selection as <strong>object</strong>)</legend>
<select ng-model="my_os" ng-options="os.name for os in osList track by os.id">
<option value="">--Select--</option>
</select>
{{my_os}}
</fieldset>
<!--//************ EXAMPLE 2 *******************-->
<fieldset>
<legend>Example 2 (Set selection as <strong>value</strong>. Simulate ajax)</legend>
<select ng-model="my_site" ng-options="site.id as site.name for site in siteList">
<option value="">--Select--</option>
</select>
{{my_site}}
</fieldset>
</div>
$scope.items = [{name: 'a', age: 20},{ name: 'b', age: 30},{ name: 'c', age: 40}];
Case-1) étiquette de la valeur dans le tableau:
<div>
<p>selected item is : {{selectedItem}}</p>
<p> age of selected item is : {{selectedItem.age}} </p>
<select ng-model="selectedItem" ng-options="item.name for item in items">
</select>
</div>
Explication de sortie (supposons que le premier élément sélectionné):
selectedItem = {name: 'a', age: 20} // [par défaut, l'élément sélectionné est égal à la valeur élément ]
selectedItem.age = 20
Case-2) sélectionne comme étiquette pour la valeur dans le tableau:
<div>
<p>selected item is : {{selectedItem}}</p>
<select ng-model="selectedItem" ng-options="item.age as item.name for item in items">
</select>
</div>
Explication de sortie (en supposant que le premier élément sélectionné): selectedItem = 20 // [la partie sélectionnée est item.age ]
Voici comment je résous ce problème dans une application héritée:
ng-options="kitType.name for kitType in vm.kitTypes track by kitType.id" ng-model="vm.itemTypeId"
vm.kitTypes = [
{"id": "1", "name": "Virtual"},
{"id": "2", "name": "Physical"},
{"id": "3", "name": "Hybrid"}
];
...
vm.itemTypeId = vm.kitTypes.filter(function(value, index, array){
return value.id === (vm.itemTypeId || 1);
})[0];
Mon HTML affiche correctement la valeur de l’option.
Comme beaucoup de gens l'ont déjà dit, si j'ai des données, cela ressemble à ceci:
countries : [
{
"key": 1,
"name": "UAE"
},
{
"key": 2,
"name": "India"
},
{
"key": 3,
"name": "OMAN"
}
]
Je voudrais l'utiliser comme:
<select
ng-model="selectedCountry"
ng-options="obj.name for obj in countries">
</select>
Dans votre contrôleur, vous devez définir une valeur initiale pour supprimer le premier élément vide:
$scope.selectedCountry = $scope.countries[0];
// You need to watch changes to get selected value
$scope.$watchCollection(function() {
return $scope.selectedCountry
}, function(newVal, oldVal) {
if (newVal === oldVal) {
console.log("nothing has changed " + $scope.selectedCountry)
}
else {
console.log('new value ' + $scope.selectedCountry)
}
}, true)