Initialisation de select avec AngularJS et ng-repeat

133

J'essaie d'obtenir la boîte de sélection pour commencer avec une option pré-remplie en utilisant ng-repeat avec AngularJS 1.1.5. Au lieu de cela, la sélection commence toujours par rien de sélectionné. Il a également une option vide, dont je ne veux pas. Je pense qu'il y a un effet secondaire du fait que rien n'est sélectionné.

Je peux faire fonctionner cela en utilisant ng-options au lieu de ng-repeat, mais je veux utiliser ng-repeat pour ce cas. Bien que mon exemple réduit ne le montre pas, je souhaite également définir l'attribut title de chaque option, et il n'y a aucun moyen de le faire en utilisant ng-options, pour autant que je sache.

Je ne pense pas que cela soit lié au problème commun de portée / héritage prototypique AngularJs. Au moins, je ne vois rien d'évident lors de l'inspection à Batarang. De plus, lorsque vous choisissez une option dans la sélection avec l'interface utilisateur, le modèle se met à jour correctement.

Voici le HTML:

<body ng-app ng-controller="AppCtrl">
    <div>
        Operator is: {{filterCondition.operator}}
    </div>
    <select ng-model="filterCondition.operator">
       <option 
           ng-repeat="operator in operators" 
           value="{{operator.value}}"
       >
           {{operator.displayName}}
       </option>
    </select>
</body>

Et le JavaScript:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]
}

JS Fiddle pour cela: http://jsfiddle.net/coverbeck/FxM3B/2/

Charles O.
la source
1
ngOption a été créé car il n'y avait aucun moyen propre de le faire avec ngRepeat. ngRepeat se déroule une fois l'option sélectionnée. Avez-vous essayé de définir ngSelect sur vos options
TheSharpieOne
Oui! Le ngSelected a fonctionné! Je publierai un JsFiddle fonctionnel mis à jour.
Charles O.
Il convient de noter que dans AngualrJS 1.2 ce code fonctionne différemment - Il ne crée pas un nouvel élément <OPTION> vide, cependant, il ne peut sélectionner que la première option dans la liste. Vous pouvez le voir ici
VitalyB

Réponses:

226

D'ACCORD. Si vous ne souhaitez pas utiliser la méthode correcte ng-options, vous pouvez ajouter un ng-selectedattribut avec une logique de vérification de condition pour que la optiondirective fasse fonctionner la présélection.

<select ng-model="filterCondition.operator">
    <option ng-selected="{{operator.value == filterCondition.operator}}"
            ng-repeat="operator in operators"
            value="{{operator.value}}">
      {{operator.displayName}}
    </option>
</select>

Working Demo

zs2020
la source
37
Je vais vous donner le crédit puisque vous l'avez compris vous-même et que vous avez fait l'exemple complet. Bien que je ne sois pas d'accord avec votre commentaire sur le fait que ng-options est la "bonne manière". :) J'ai toujours utilisé ng-options moi-même, mais cela nécessitait de faire quelque chose que ng-options ne supporte pas, aussi petit soit-il. Et le document Angular dit que vous pouvez également répéter. Merci, Charles
Charles O.
Merci, c'était un moyen simple de désactiver certaines options.
Dorian
11
ng-options n'est correct que tant que ses cas d'utilisation correspondent au vôtre. Vous aurez peut-être besoin d'attributs / classes supplémentaires dans les champs option / optgroup, etc.
mystrdat
6
"la bonne manière" ne fonctionne pas parfois (par exemple si vous voulez traduire les chaînes qui remplissent les noms des options)
btk
11
Je pense que l'expression ng-selected doit être sans {{}}: ng-selected = "operator.value == filterCondition.operator"
mvermand
35

Pour la balise select, angular fournit la directive ng-options. Il vous donne le cadre spécifique pour configurer les options et définir une valeur par défaut. Voici le violon mis à jour utilisant ng-options qui fonctionne comme prévu: http://jsfiddle.net/FxM3B/4/

HTML mis à jour (le code reste le même)

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.value as operator.displayName for operator in operators">
</select>
</body>
Jeremy Likness
la source
3
Salut Jeremy - J'essaye de faire ça sans ng-options. Comme je l'ai dit dans ma question et en réponse à Shaun, je voudrais définir l'attribut title sur chaque option, et je ne peux pas le faire avec ng-options, pour autant que je sache. Merci, Charles
Charles O.5
9

Merci à TheSharpieOne pour avoir signalé l'option ng-selected. Si cela avait été affiché comme une réponse plutôt que comme un commentaire, j'aurais donné la bonne réponse.

Voici un JSFiddle fonctionnel: http://jsfiddle.net/coverbeck/FxM3B/5/ .

J'ai également mis à jour le violon pour utiliser l'attribut title, que j'avais omis dans mon message d'origine, car ce n'était pas la cause du problème (mais c'est la raison pour laquelle je veux utiliser ng-repeat au lieu de ng-options) .

HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator">
   <option ng-repeat="operator in operators" title="{{operator.title}}" ng-selected="{{operator.value == filterCondition.operator}}" value="{{operator.value}}">{{operator.displayName}}</option>
</select>
</body>

JS:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals', title: 'The equals operator does blah, blah'},
        {value: 'neq', displayName: 'not equal', title: 'The not equals operator does yada yada'}
     ]
}
Charles O.
la source
Désolé d'avoir publié un commentaire. Je n'avais pas envie de faire un exemple et je n'étais pas sûr à 100% que cela fonctionnerait. C'était juste une intuition.
TheSharpieOne
9

Le fait qu'angular injecte un élément d'option vide dans la sélection est que l'objet de modèle qui lui est lié par défaut est livré avec une valeur vide lors de l'initialisation.

Si vous souhaitez sélectionner une option par défaut, vous pouvez probablement la définir sur l'oscilloscope dans le contrôleur

$scope.filterCondition.operator = "your value here";

Si vous voulez un espace réservé d'option vide, cela fonctionne pour moi

<select ng-model="filterCondition.operator" ng-options="operator.id as operator.name for operator in operators">
  <option value="">Choose Operator</option>
</select>
Ammadu
la source
2
C'est bien, mais Angular crée une option vide. Comment éviter cela?
MarceloBarbosa
1

Comme suggéré, vous devez utiliser ng-options et, malheureusement, je pense que vous devez référencer l'élément de tableau par défaut (à moins que le tableau ne soit un tableau de chaînes).

http://jsfiddle.net/FxM3B/3/

Le JavaScript:

function AppCtrl($scope) {


    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]

    $scope.filterCondition={
        operator: $scope.operators[0]
    }
}

Le HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator.value}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.displayName for operator in operators">
</select>
</body>
shaunhusain
la source
Savez-vous pourquoi et êtes-vous sûr? La documentation ( docs.angularjs.org/api/ng.directive:select ) indique que vous devez uniquement utiliser ng-options lors de la liaison à une valeur non-chaîne. Comme je l'ai dit, je veux utiliser l'attribut title, et il n'y a aucun moyen de le faire avec ng-options. Quelque chose comme <option title = "Une très longue description de ce choix" ...> Merci.
Charles O.
Je pense que la note dans la documentation n'est pas claire et signifie en fait que vous devrez utiliser une chaîne pour le modèle et disposer d'un tableau de chaînes pour les options. Si cela ne vous dérange pas quel est le raisonnement pour utiliser l'attribut "title", je ne le vois pas sur W3C w3schools.com/tags/tag_option.asp et je ne me souviens pas de l'avoir vraiment utilisé. Ne pourriez-vous pas simplement stocker la description dans les objets, puis récupérer ces données puisque c'est à cela que le modèle est maintenant lié?
shaunhusain
Sur la page W3C à laquelle vous vous êtes connecté, si vous cliquez sur le lien Attributs globaux, vous verrez que l'attribut title est pris en charge par l'élément option. J'utilise l'attribut title uniquement pour afficher le texte "info-bulle", de sorte que si vous survolez une option, vous pouvez obtenir une description plus détaillée de ce que signifie l'option. C'est une petite chose, mais ce serait bien d'avoir, si possible.
Charles O.
@CharlesO. Je veux faire exactement comme toi. Définissez un objet (valeur non-string) mais je souhaite également utiliser un titre dans la liste d'options. Y a-t-il une solution pour cela. Je n'arrive pas à le trouver ...
Wilt
1

Si vous utilisez md-select et ng-repeat ing md-option à partir d'un matériau angulaire, vous pouvez ajouter ng-model-options="{trackBy: '$value.id'}"à la balise md-select ash montrée dans ce stylo

Code:

<md-select ng-model="user" style="min-width: 200px;" ng-model-options="{trackBy: '$value.id'}">
  <md-select-label>{{ user ? user.name : 'Assign to user' }}</md-select-label>
  <md-option ng-value="user" ng-repeat="user in users">{{user.name}}</md-option>
</md-select>

Japhet Ongeri - inkalimeva
la source