Usando una coma como separador de lista con AngularJS

179

Necesito crear una lista de elementos separados por comas:

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

De acuerdo con la documentación de AngularJS, no se permiten declaraciones de flujo de control en las expresiones. Por eso mi{{$last ? '' : ', '}} no funciona.

¿Hay alguna forma alternativa de crear listas separadas por comas?

EDITAR 1
¿hay algo más simple que:

<span ng-show="!$last">, </span>
Franck Freiburger
fuente
55
Siempre puede usar CSS para formatear listas de esta manera (entonces no necesita modificar HTML cuando su jefe las quiere en líneas separadas, etc.) - consulte stackoverflow.com/questions/1517220/…
AlexFoxGill

Respuestas:

338

Podrías hacerlo de esta manera:

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

..Pero me gusta la respuesta de Philipp :-)

Andrew Joslin
fuente
¿No debería ($last && '' || ', ')ceder siempre ', '?
okm
15
Al igual que arriba, no pude ser angular para evaluar adecuadamente $ last a verdadero o falso dentro de una plantilla. He utilizado este: {{{true: '', false: ', '}[$last]}}. Esta técnica es más flexible que el uso .joinporque permite que los elementos de la lista sean miembros de una matriz, como:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus
3
Actualizado para usar operadores ternarios
Andrew Joslin
1
¿Cómo puedo insertar y en la matriz impresa para que mi matriz se vea así: John, Mike y Nil. Cómo obtener este formato sin usar la directiva.
MaTya
Estoy usando este enfoque ya que me permite usar un filtro en cada valor de la lista.
C Fairweather
231

Simplemente use la función incorporada de Javascript join(separator)para las matrices:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Philipp Reichart
fuente
21
Si desea separadores HTML-ish, probablemente sea hora de escribir una directiva . También podría poner HTML join()y deshabilitar el escape de HTML, pero hay un lugar especial en el infierno para eso;)
Philipp Reichart
Bien, ni siquiera pensé en usarlo de esta manera.
Fresa
@DavidKEgghead Ruego diferir, jsfiddle.net/wuZRA . ¿Cómo no te funciona?
Philipp Reichart
2
@PhilippReichart perdón por la demora. Aquí hay un ejemplo: jsfiddle.net/Sek8F : parece que está apuntando a una cadena donde me estoy refiriendo a un objeto.
Ravi Ram
101

También:

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

Y en plantilla:

{{ itemsArray | joinBy:',' }}
sanusart
fuente
11
Esta respuesta muestra "forma angular" y debe marcarse como la mejor.
Eugene Griaznov
14
¿Por qué no guardar seis líneas y simplemente hacer {{ itemsArray.join(', ') }}?
Philipp Reichart
12
No estoy seguro de reescribir las funciones básicas de JavaScript en AngularJS es realmente "la forma angular" ...
Michael Cole
1
Esta respuesta muestra cómo Angular puede agregar valor para las matrices de objetos
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
fuente
1
Esto parece ser la forma más "semántica", ya que la elección de usar una lista separada por comas es totalmente sobre la presentación. También podría haber sido una sublista.
Elliot Cameron
Esta fue la primera solución que vino a mi mente. Menos dependiente de JavaScript.
Kalpesh Panchal
10

Puedes usar CSS para arreglarlo también

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

Pero la respuesta de Andy Joslin es la mejor

Editar: cambié de opinión, tenía que hacer esto recientemente y terminé con un filtro de combinación.

Chris Stephens
fuente
2
También elegiría un filtro personalizado, pero me gusta tu idea :)
JBC
5

Creo que es mejor usarlo ng-if. ng-showcrea un elemento en domy lo establece display:none. Cuantos más domelementos tenga, más recursos necesitará su aplicación, y en dispositivos con menos recursos, menosdom elementos, mejor.

TBH <span ng-if="!$last">, </span>parece ser una excelente manera de hacerlo. Es sencillo.

the7erm
fuente
Me gusta este enfoque, ya que es simple y aún admite separadores basados ​​en html. Gracias @ the7erm!
alexkb
2

Como esta pregunta es bastante antigua y AngularJS ha tenido tiempo de evolucionar desde entonces, ahora se puede lograr fácilmente usando:

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

Tenga en cuenta que estoy usando en ngBindlugar de la interpolación, {{ }}ya que es mucho más eficiente: ngBind solo se ejecutará cuando el valor pasado realmente cambie. Los corchetes {{ }}, por otro lado, serán revisados ​​y actualizados en cada $ digest, incluso si no es necesario. Fuente: aquí , aquí y aquí .

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>

En una nota final, todas las soluciones aquí funcionan y son válidas hasta el día de hoy. Realmente me encuentro con aquellos que involucran CSS ya que esto es más un problema de presentación.

Cosmin Ababei
fuente
1

Me gusta el enfoque de simbu, pero no me siento cómodo con el primer hijo o el último hijo. En cambio, solo modifico el contenido de una clase repetida de lista-coma.

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

Si está utilizando ng-show para limitar los valores, {{$last ? '' : ', '}}no funcionará, ya que aún tendrá en cuenta todos los valores.

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

Resulta en agregar una coma después del "último" valor , ya que con ng-show todavía tiene en cuenta los 4 valores

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

Una solución es agregar un filtro directamente en ng-repeat

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

Resultados

{"email":"1"},
{"email":"1"}
Mihai
fuente
¿Alguna sugerencia sobre cómo resolver este problema de la misma manera en Angular 2 sin crear una tubería personalizada?
chaenu