web-dev-qa-db-fra.com

Travailler avec select en utilisant les options de AngularJS

J'ai lu à ce sujet dans d'autres posts, mais je ne pouvais pas le comprendre.

J'ai un tableau,

$scope.items = [
   {ID: '000001', Title: 'Chicago'},
   {ID: '000002', Title: 'New York'},
   {ID: '000003', Title: 'Washington'},
];

Je veux le rendre comme:

<select>
  <option value="000001">Chicago</option>
  <option value="000002">New York</option>
  <option value="000003">Washington</option>
</select>

Et aussi je veux sélectionner l'option avec ID = 000002.

J'ai lu sélectionnez et essayé, mais je n'arrive pas à le comprendre.

432
Andrej Kaurin

Une chose à noter est que ngModel est requis pour que ngOptions fonctionne ... notez le ng-model="blah" qui dit "set $ scope.blah à la valeur sélectionnée".

Essaye ça:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

Voici plus de la documentation de AngularJS (si vous ne l'avez pas vue):

pour les sources de données de tableau:

  • étiquette pour la valeur dans le tableau
  • sélectionner comme étiquette pour la valeur dans le tableau
  • groupe d'étiquettes par groupe pour valeur dans tableau = sélectionner comme étiquette groupe par groupe pour valeur dans tableau

pour les sources de données objet:

  • étiquette pour (clé, valeur) dans l'objet
  • sélectionner comme étiquette pour (clé, valeur) dans l'objet
  • label groupe par groupe pour (clé, valeur) dans l'objet
  • sélectionner comme étiquette groupe par groupe pour (clé, valeur) dans l'objet

Pour plus de précisions sur les valeurs des balises d'options dans AngularJS:

Lorsque vous utilisez ng-options, , les valeurs des balises option écrites par ng-options seront toujours l'index de l'élément de tableau auquel se rapporte la balise option . En effet, AngularJS vous permet en réalité de sélectionner des objets entiers avec des contrôles de sélection, et pas seulement des types primitifs. Par exemple:

app.controller('MainCtrl', function($scope) {
   $scope.items = [
     { id: 1, name: 'foo' },
     { id: 2, name: 'bar' },
     { id: 3, name: 'blah' }
   ];
});
<div ng-controller="MainCtrl">
   <select ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
   <pre>{{selectedItem | json}}</pre>
</div>

Ce qui précède vous permettra de sélectionner directement un objet entier dans $scope.selectedItem. En fait, avec AngularJS, vous n'avez pas à vous soucier de ce qui se trouve dans votre balise d'option. Laissez AngularJS gérer cela; vous ne devez vous soucier que de ce que votre modèle contient dans votre champ d'application.

Voici un dépliant montrant le comportement ci-dessus et montrant le code HTML écrit


Traiter avec l'option par défaut:

J'ai omis de mentionner ci-dessus quelques éléments relatifs à l'option par défaut.

Sélection de la première option et suppression de l'option vide:

Vous pouvez le faire en ajoutant un simple ng-init qui définit le modèle (de ng-model) au premier élément des éléments que vous répétez dans ng-options:

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

Note: Cela pourrait devenir un peu fou si foo était initialisé correctement à quelque chose de "faux". Dans ce cas, vous souhaiterez probablement gérer l'initialisation de foo dans votre contrôleur.

Personnalisation de l'option par défaut:

C'est un peu différent; Ici, tout ce que vous avez à faire est d’ajouter une balise option en tant qu’enfant de votre sélection, avec un attribut value vide, puis de personnaliser son texte intérieur:

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

Remarque: Dans ce cas, l'option "vide" y restera même après avoir sélectionné une autre option. Ce n'est pas le cas pour le comportement par défaut de selects sous AngularJS.

Une option par défaut personnalisée qui se cache après la sélection:

Si vous souhaitez que votre option par défaut personnalisée disparaisse après la sélection d'une valeur, vous pouvez ajouter un attribut ng-hide à votre option par défaut:

<select ng-model="foo" ng-options="item as item.name for item in items">
   <option value="" ng-if="foo">Select something to remove me.</option>
</select>
790
Ben Lesh

J'apprends AngularJS et je me battais aussi avec la sélection. Je sais que cette question a déjà reçu une réponse, mais je voulais quand même partager un peu plus de code.

Dans mon test, j'ai deux listes déroulantes: marques et modèles de voitures. La liste des modèles est désactivée jusqu'à ce qu'une marque soit sélectionnée. Si la sélection dans la liste fabrique est réinitialisée ultérieurement (définie sur "Sélectionner marque"), la liste déroulante des modèles redevient désactivée ET sa sélection est également réinitialisée (sur "Sélectionner un modèle"). Les marques sont récupérées en tant que ressource, tandis que les modèles sont simplement codés en dur.

Fait JSON:

[
{"code": "0", "name": "Select Make"},
{"code": "1", "name": "Acura"},
{"code": "2", "name": "Audi"}
]

services.js:

angular.module('makeServices', ['ngResource']).
factory('Make', function($resource){
    return $resource('makes.json', {}, {
        query: {method:'GET', isArray:true}
    });
});

Fichier HTML:

<div ng:controller="MakeModelCtrl">
  <div>Make</div>
  <select id="makeListBox"
      ng-model="make.selected"
      ng-options="make.code as make.name for make in makes"
      ng-change="makeChanged(make.selected)">
  </select>

  <div>Model</div>
  <select id="modelListBox"
     ng-disabled="makeNotSelected"
     ng-model="model.selected"
     ng-options="model.code as model.name for model in models">
  </select>
</div>

controllers.js:

function MakeModelCtrl($scope)
{
    $scope.makeNotSelected = true;
    $scope.make = {selected: "0"};
    $scope.makes = Make.query({}, function (makes) {
         $scope.make = {selected: makes[0].code};
    });

    $scope.makeChanged = function(selectedMakeCode) {
        $scope.makeNotSelected = !selectedMakeCode;
        if ($scope.makeNotSelected)
        {
            $scope.model = {selected: "0"};
        }
    };

    $scope.models = [
      {code:"0", name:"Select Model"},
      {code:"1", name:"Model1"},
      {code:"2", name:"Model2"}
    ];
    $scope.model = {selected: "0"};
}
89
mp31415

Pour une raison quelconque, AngularJS permet de me confondre. Leur documentation est assez horrible à ce sujet. Plus de bons exemples de variations seraient les bienvenus.

Quoi qu'il en soit, j'ai une légère variation sur la réponse de Ben Lesh.

Mes collections de données ressemblent à ceci:

items =
[
   { key:"AD",value:"Andorra" }
,  { key:"AI",value:"Anguilla" }
,  { key:"AO",value:"Angola" }
 ...etc..
]

Maintenant

<select ng-model="countries" ng-options="item.key as item.value for item in items"></select>

la valeur des options correspond toujours à l’indice (0, 1, 2, etc.).

L'ajout de Track By l'a corrigé pour moi:

<select ng-model="blah" ng-options="item.value for item in items track by item.key"></select>

Je pense qu'il arrive plus souvent que vous souhaitiez ajouter un tableau d'objets à une liste de sélection, je vais donc me souvenir de celle-ci!

Sachez qu'à partir de AngularJS 1.4, vous ne pouvez plus utiliser ng-options, mais vous devez utiliser ng-repeat sur votre balise d'option:

<select name="test">
   <option ng-repeat="item in items" value="{{item.key}}">{{item.value}}</option>
</select>
38
Mattijs

La question a déjà été répondue (BTW, réponse vraiment bonne et complète fournie par Ben), mais je voudrais ajouter un autre élément d’intégralité, qui peut également être très utile.

Dans l'exemple proposé par Ben:

<select ng-model="blah" ng-options="item.ID as item.Title for item in items"></select>

le formulaire ngOptions suivant a été utilisé: select as label for value in array.

Label est une expression dont le résultat sera l'étiquette de l'élément <option>. Dans ce cas, vous pouvez effectuer certaines concaténations de chaînes afin d’avoir des étiquettes d’option plus complexes.

Exemples:

  • ng-options="item.ID as item.Title + ' - ' + item.ID for item in items" vous donne des étiquettes comme Title - ID
  • ng-options="item.ID as item.Title + ' (' + item.Title.length + ')' for item in items" vous donne des étiquettes comme Title (X), où X est la longueur de la chaîne de titre.

Vous pouvez également utiliser des filtres, par exemple,

  • ng-options="item.ID as item.Title + ' (' + (item.Title | uppercase) + ')' for item in items" vous donne des libellés tels que Title (TITLE), où la valeur Title de la propriété Title et TITLE est identique, mais convertie en majuscules.
  • ng-options="item.ID as item.Title + ' (' + (item.SomeDate | date) + ')' for item in items" vous donne des étiquettes telles que Title (27 Sep 2015), si votre modèle a une propriété SomeDate
15
Tom

Dans CoffeeScript:

#directive
app.directive('select2', ->
    templateUrl: 'partials/select.html'
    restrict: 'E'
    transclude: 1
    replace: 1
    scope:
        options: '='
        model: '='
    link: (scope, el, atr)->
        el.bind 'change', ->
            console.log this.value
            scope.model = parseInt(this.value)
            console.log scope
            scope.$apply()
)
<!-- HTML partial -->
<select>
  <option ng-repeat='o in options'
          value='{{$index}}' ng-bind='o'></option>
</select>

<!-- HTML usage -->
<select2 options='mnuOffline' model='offlinePage.toggle' ></select2>

<!-- Conclusion -->
<p>Sometimes it's much easier to create your own directive...</p>
7
Akatsuki Sai

Si vous avez besoin d'un titre personnalisé pour chaque option, ng-options ne s'applique pas. Utilisez plutôt ng-repeat avec les options suivantes:

<select ng-model="myVariable">
  <option ng-repeat="item in items"
          value="{{item.ID}}"
          title="Custom title: {{item.Title}} [{{item.ID}}]">
       {{item.Title}}
  </option>
</select>
6
Dmitri Algazin

J'espère que ce qui suit fonctionnera pour vous.

<select class="form-control"
        ng-model="selectedOption"
        ng-options="option.name + ' (' + (option.price | currency:'USD$') + ')' for option in options">
</select>
3
Meghshyam Sonar

Cela peut être utile. Les fixations ne fonctionnent pas toujours.

<select id="product" class="form-control" name="product" required
        ng-model="issue.productId"
        ng-change="getProductVersions()"
        ng-options="p.id as p.shortName for p in products"></select>

Par exemple, vous remplissez le modèle source de liste d'options à partir d'un service REST. Une valeur sélectionnée était connue avant de remplir la liste et elle était définie. Après avoir exécuté la demande REST avec $ http, l'option de liste est terminée.

Mais l'option sélectionnée n'est pas définie. Pour des raisons inconnues, AngularJS dans shadow $ digest en cours d’exécution ne lie pas comme il se doit. Je dois utiliser jQuery pour définir le sélectionné. C'est important! AngularJS, dans l’ombre, ajoute le préfixe à la valeur de la "valeur" attr pour les options générées par ng-repeat. Pour int c'est "numéro:".

$scope.issue.productId = productId;
function activate() {
    $http.get('/product/list')
       .then(function (response) {
           $scope.products = response.data;

           if (productId) {
               console.log("" + $("#product option").length);//for clarity
               $timeout(function () {
                   console.log("" + $("#product option").length);//for clarity
                   $('#product').val('number:'+productId);

               }, 200);
           }
       });
}
1
trueboroda