Utilisation de la virgule comme séparateur de liste avec AngularJS

179

J'ai besoin de créer une liste d'éléments séparés par des virgules:

  <li ng-repeat="friend in friends">
      <b ng-repeat="email in friend.email">{{email}}{{$last ? '' : ', '}}</b>...
  </li>

Selon la documentation AngularJS, aucune instruction de flux de contrôle n'est autorisée dans les expressions. C'est pourquoi mon {{$last ? '' : ', '}}ne fonctionne pas.

Existe-t-il un autre moyen de créer des listes séparées par des virgules?

EDIT 1
est-il quelque chose de plus simple que:

<span ng-show="!$last">, </span>
Franck Freiburger
la source
5
Vous pouvez toujours utiliser CSS pour formater les listes de cette manière (vous n'avez pas besoin de modifier le HTML lorsque votre patron le veut sur des lignes séparées, etc.) - voir stackoverflow.com/questions/1517220/…
AlexFoxGill

Réponses:

338

Vous pouvez le faire de cette façon:

<b ng-repeat="email in friend.email">{{email}}{{$last ? '' : ', '}}</b>

..Mais j'aime la réponse de Philipp :-)

Andrew Joslin
la source
Ne devrait pas ($last && '' || ', ')toujours céder ', '?
okm
15
Comme okm ci-dessus, je ne pouvais pas être angulaire pour évaluer correctement $ last à vrai ou faux dans un modèle. Je ceci: {{{true: '', false: ', '}[$last]}}. Cette technique est plus flexible que l'utilisation .joincar elle permet aux éléments de la liste d'être chacun membres d'un tableau, comme:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus
3
Mise à jour pour utiliser les opérateurs ternaires
Andrew Joslin
1
Comment puis-je insérer et dans le tableau imprimé pour que mon tableau ressemble à ceci: John, Mike et Nil. Comment obtenir ce format sans utiliser de directive.
MaTya
J'utilise cette approche car elle me permet d'utiliser un filtre sur chaque valeur de la liste.
C Fairweather
231

Utilisez simplement la fonction intégrée de Javascript join(separator)pour les tableaux:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Philipp Reichart
la source
21
Si vous voulez des séparateurs HTML-ish, il est probablement temps d'utiliser une directive d' écriture . Vous pouvez également insérer du HTML join()et désactiver l'échappement HTML, mais il y a une place spéciale en enfer pour cela;)
Philipp Reichart
Bien, je n'ai même pas pensé à l'utiliser de cette façon.
Strawberry
@DavidKEgghead Je ne suis pas d' accord , jsfiddle.net/wuZRA . Comment ça ne marche pas pour vous?
Philipp Reichart
2
@PhilippReichart désolé pour le retard. Voici un exemple: jsfiddle.net/Sek8F - on dirait que vous ciblez une chaîne où je fais référence à un objet.
Ravi Ram
101

Aussi:

angular.module('App.filters', [])
    .filter('joinBy', function () {
        return function (input,delimiter) {
            return (input || []).join(delimiter || ',');
        };
    });

Et dans le modèle:

{{ itemsArray | joinBy:',' }}
Sanusart
la source
11
Cette réponse montre "voie angulaire" et devrait être marquée comme la meilleure.
Eugene Griaznov
14
Pourquoi ne pas enregistrer six lignes et le faire {{ itemsArray.join(', ') }}?
Philipp Reichart
12
Je ne suis pas sûr que la réécriture des fonctions de base JavaScript dans AngularJS soit vraiment "à la manière angulaire" ...
Michael Cole
1
Cette réponse montre comment Angular peut ajouter de la valeur aux tableaux d'objets
Michael Cole
41

.list-comma::before {
  content: ',';
}
.list-comma:first-child::before {
  content: '';
}
<span class="list-comma" ng-repeat="destination in destinations">
                            {{destination.name}}
                        </span>

simbu
la source
1
Cela semble être la manière la plus «sémantique», car le choix d'utiliser une liste séparée par des virgules est entièrement une question de présentation. Cela aurait tout aussi bien pu être une sous-liste.
Elliot Cameron
C'était la première solution qui m'est venue à l'esprit. Moins dépendant de JavaScript.
Kalpesh Panchal
10

Vous pouvez également utiliser CSS pour le corriger

<div class="some-container">
[ <span ng-repeat="something in somethings">{{something}}<span class="list-comma">, </span></span> ]
</div>

.some-container span:last-child .list-comma{
    display: none;
}

Mais la réponse d'Andy Joslin est la meilleure

Edit: j'ai changé d'avis, je devais le faire récemment et j'ai fini par utiliser un filtre de jointure.

Chris Stephens
la source
2
J'irais aussi pour un filtre personnalisé, mais j'aime votre idée :)
JBC
5

Je pense qu'il vaut mieux l'utiliser ng-if. ng-showcrée un élément dans le domet le définit display:none. Plus domvous avez d'éléments, plus votre application est gourmande en ressources, et sur les appareils avec moins de ressources, moins il y a d' doméléments, mieux c'est.

TBH <span ng-if="!$last">, </span>semble être un excellent moyen de le faire. C'est simple.

the7erm
la source
J'aime cette approche, car elle est simple et prend toujours en charge les séparateurs basés sur html. Merci @ the7erm!
alexkb
2

Comme cette question est assez ancienne et qu'AngularJS a eu le temps d'évoluer depuis, cela peut maintenant être facilement réalisé en utilisant:

<li ng-repeat="record in records" ng-bind="record + ($last ? '' : ', ')"></li>.

Notez que j'utilise à la ngBindplace de l'interpolation {{ }}car c'est beaucoup plus performant: ngBind ne fonctionnera que lorsque la valeur passée change réellement. Les parenthèses {{ }}, par contre, seront vérifiées et actualisées dans chaque $ digest, même si ce n'est pas nécessaire. Source: ici , ici et ici .

angular
  .module('myApp', [])
  .controller('MyCtrl', ['$scope',
    function($scope) {
      $scope.records = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    }
  ]);
li {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
  <ul>
    <li ng-repeat="record in records" ng-bind="record + ($last ? '' : ', ')"></li>
  </ul>
</div>

Sur une note finale, toutes les solutions ici fonctionnent et sont valables à ce jour. Je suis vraiment tombé sur ceux qui impliquent CSS car il s'agit plus d'un problème de présentation.

Cosmin Ababei
la source
1

J'aime l'approche de simbu, mais je ne suis pas à l'aise d'utiliser le premier ou le dernier enfant. Au lieu de cela, je ne modifie que le contenu d'une classe répétitive de liste-virgule.

.list-comma + .list-comma::before {
    content: ', ';
}
<span class="list-comma" ng-repeat="destination in destinations">
    {{destination.name}}
</span>
Durrahan
la source
0

Si vous utilisez ng-show pour limiter les valeurs, cela {{$last ? '' : ', '}}ne fonctionnera pas car il prendra toujours en compte toutes les valeurs.

<div ng-repeat="x in records" ng-show="x.email == 1">{{x}}{{$last ? '' : ', '}}</div>

var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope) {
  $scope.records = [
    {"email": "1"},
    {"email": "1"},
    {"email": "2"},
    {"email": "3"}
  ]
});

Résultat en ajoutant une virgule après la "dernière" valeur , car avec ng-show, il prend toujours en compte les 4 valeurs

{"email":"1"},
{"email":"1"},

Une solution consiste à ajouter un filtre directement dans ng-repeat

<div ng-repeat="x in records | filter: { email : '1' } ">{{x}}{{$last ? '' : ', '}}</div>

Résultats

{"email":"1"},
{"email":"1"}
Mihai
la source
Une suggestion sur la façon de résoudre ce problème de la même manière dans Angular 2 sans créer de tuyau personnalisé?
chaenu