Utilizzo della virgola come separatore di elenco con AngularJS


179

Devo creare un elenco di elementi separati da virgole:

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

Secondo la documentazione di AngularJS, nelle espressioni non sono consentite istruzioni sul flusso di controllo. Questo è il motivo per cui il mio {{$last ? '' : ', '}}non funziona.

Esiste un modo alternativo per creare elenchi separati da virgola?

EDIT 1
c'è qualcosa di più semplice di:

<span ng-show="!$last">, </span>

5
È sempre possibile utilizzare i CSS per la formattazione di elenchi in questo modo (quindi non c'è bisogno di modificare HTML quando il tuo capo li vuole su righe separate, ecc) - vedi stackoverflow.com/questions/1517220/...
AlexFoxGill

Risposte:


338

Potresti farlo in questo modo:

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

..Ma mi piace la risposta di Philipp :-)


Non dovrebbe ($last && '' || ', ')sempre cedere ', '?
okm

15
Come sopra, non riuscivo a ottenere angolare per valutare correttamente $ last su true o false all'interno di un modello. Ho usato questo: {{{true: '', false: ', '}[$last]}}. Questa tecnica è più flessibile dell'uso .joinperché consente agli elementi nell'elenco di essere membri di un array, come:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus

3
Aggiornato per utilizzare gli operatori ternari
Andrew Joslin,

1
Come posso inserire e nell'array stampato in modo che il mio array assomigli a questo: John, Mike e Nil. Come ottenere questo formato senza usare la direttiva.
MaTya,

Sto usando questo approccio poiché mi consente di utilizzare un filtro su ciascun valore nell'elenco.
C Fairweather,

231

Basta usare la funzione integrata di Javascript join(separator)per gli array:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>

21
Se vuoi separatori HTML-ish è probabilmente il momento di una direttiva di scrittura . Puoi anche inserire HTML join()e disabilitare l'escaping HTML, ma c'è un posto speciale all'inferno per quello;)
Philipp Reichart,

Bello, non ho nemmeno pensato di usarlo in questo modo.
Strawberry,

@DavidKEgghead Mi permetto di dissentire, jsfiddle.net/wuZRA . Come non funziona per te?
Philipp Reichart,

2
@PhilippReichart scusate il ritardo. Ecco un esempio: jsfiddle.net/Sek8F - sembra che tu stia prendendo di mira una stringa in cui mi riferisco a un oggetto.
Ravi Ram,

101

Anche:

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

E nel modello:

{{ itemsArray | joinBy:',' }}

11
Questa risposta mostra "via angolare" e deve essere contrassegnata come la migliore.
Eugene Griaznov,

14
Perché non salvare sei righe e basta {{ itemsArray.join(', ') }}?
Philipp Reichart,

12
Non sono sicuro che riscrivere le funzioni principali di JavaScript in AngularJS sia davvero "la via angolare" ...
Michael Cole,

1
Questa risposta mostra come Angular può aggiungere valore per le matrici di oggetti
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>


1
Questo sembra il modo più "semantico", poiché la scelta di usare un elenco separato da virgole è interamente sulla presentazione. Potrebbe anche essere stato un elenco secondario.
Elliot Cameron,

Questa è stata la prima soluzione che mi è venuta in mente. Meno dipendente da JavaScript.
Kalpesh Panchal,

10

Puoi anche usare CSS per risolverlo

<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;
}

Ma la risposta di Andy Joslin è la migliore

Modifica: ho cambiato idea, ho dovuto farlo di recente e ho finito con un filtro join.


2
Vorrei anche un filtro personalizzato, ma mi piace la tua idea :)
JBC,

5

Penso che sia meglio usare ng-if. ng-showcrea un elemento in dome lo imposta display:none. Più domelementi hai, più la tua app ha fame di risorse, e su dispositivi con risorse più basse, minore è il numero di domelementi, meglio è.

TBH <span ng-if="!$last">, </span>sembra un ottimo modo per farlo. È semplice.


Mi piace questo approccio, in quanto è semplice e supporta ancora separatori basati su HTML. Grazie @ the7erm!
alexkb

2

Poiché questa domanda è piuttosto vecchia e AngularJS aveva avuto il tempo di evolversi da allora, questo ora può essere facilmente raggiunto usando:

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

Nota che sto usando l' ngBindinterpolazione invece {{ }}che è molto più performante: ngBind verrà eseguito solo quando il valore passato cambia effettivamente. Le parentesi {{ }}, d'altra parte, saranno sporche controllate e aggiornate in ogni $ digest, anche se non è necessario. Fonte: qui , qui e qui .

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>

In ultima analisi, tutte le soluzioni qui funzionano e sono valide fino ad oggi. Mi sono davvero trovato a quelli che coinvolgono CSS in quanto questo è più un problema di presentazione.


1

Mi piace l'approccio di simbu, ma non mi sento a mio agio con il primo figlio o l'ultimo figlio. Invece, modifico solo il contenuto di una classe di virgole elenco ripetuta.

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

0

Se stai usando ng-show per limitare i valori, {{$last ? '' : ', '}}non funzionerà poiché prenderà ancora in considerazione tutti i valori.

<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"}
  ]
});

Si ottiene l' aggiunta di una virgola dopo il valore "last" , poiché con ng-show prende ancora in considerazione tutti e 4 i valori

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

Una soluzione è aggiungere un filtro direttamente in ng-repeat

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

risultati

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

Qualche suggerimento su come risolvere questo problema allo stesso modo in Angular 2 senza creare una pipe personalizzata?
Chaenu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.