440 votes

Travailler avec des sélections en utilisant les ng-options d'Angular

J'ai lu d'autres articles à ce sujet, mais je n'ai pas réussi à comprendre. J'ai un tableau :

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

Je veux rendre ceci

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

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

J'ai lu ceci http://docs.angularjs.org/api/ng.directive:select J'ai essayé mais je n'arrive pas à comprendre.

797voto

Ben Lesh Points 39290

Une chose à noter est que ngModel est requis pour que les ngOptions fonctionnent... notez l'élément ng-model="blah" qui dit "définir $scope.blah à la valeur sélectionnée".

Essayez ça :

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

Voici d'autres informations tirées de la documentation d'Angular (si vous ne les avez pas vues) :

pour les sources de données de type tableau :

  • étiquette pour la valeur dans le tableau
  • sélectionner comme étiquette pour une valeur dans un tableau
  • étiquette groupe par groupe pour la valeur dans le tableau = select as label group by group pour valeur dans tableau

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

EDIT : Pour quelques éclaircissements sur les valeurs des balises d'option dans Angular

Lorsque vous utilisez ng-options , les valeurs des balises d'option écrites par ng-options seront toujours l'index de l'élément du tableau auquel la balise d'option se rapporte. . En effet, Angular vous permet 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 un objet entier en $scope.selectedItem directement. Le fait est qu'avec Angular, vous n'avez pas à vous soucier du contenu de votre balise d'option. Laissez Angular s'en occuper, vous ne devez vous préoccuper que de ce qui se trouve dans votre modèle dans votre scope.

Voici un plunker démontrant le comportement ci-dessus, et montrant le html écrit.


EDIT 2 : Traitement de l'option par défaut :

Il y a quelques éléments que j'ai omis de mentionner ci-dessus concernant 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 dans les é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 peut devenir un peu fou si foo est initialisé correctement à quelque chose de "falsy". Dans ce cas, vous devrez gérer l'initialisation de foo dans votre contrôleur, très probablement.

Personnaliser l'option par défaut :

C'est un peu différent, ici tout ce que vous devez faire est d'ajouter une balise d'option comme enfant de votre sélection, avec un attribut de valeur vide, puis de personnaliser son texte interne :

<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" restera en place même si vous sélectionnez une autre option. Ce n'est pas le cas du comportement par défaut des sélections sous Angular.

Une option par défaut personnalisée qui disparaît après qu'une sélection a été effectuée :

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>

89voto

user194715 Points 656

Je suis en train d'apprendre angularjs et j'avais également du mal avec la sélection. Je sais que cette question a déjà reçu une réponse mais je voulais néanmoins partager un peu plus de code.

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

Fabrique du 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"};
}

J'espère que cela a du sens et que cela aidera quelqu'un.

38voto

Mattijs Points 128

Pour une raison quelconque, Angular permet de m'embrouiller. 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, ceci :

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

donne toujours comme résultat que la valeur des options est l'indice (0,1,2...etc).

L'ajout de Track By a réglé le problème 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 vouliez ajouter un tableau d'objets dans une liste de sélection, donc je vais me souvenir de celui-ci !

Merci à tous pour votre aide.

7voto

Akatsuki Sai Points 39

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 its much easier to create your own directive..</p>

1voto

hewstone Points 170

Je recommande vivement d'utiliser Select2 ( http://ivaynberg.github.io/select2/#basics ) car il s'en chargera pour vous. Il existe même une directive pour angular ( https://github.com/angular-ui/ui-select2 ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X