Używanie przecinka jako separatora listy w AngularJS

179

Muszę utworzyć listę elementów oddzieloną przecinkami:

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

Zgodnie z dokumentacją AngularJS w wyrażeniach nie są dozwolone żadne instrukcje przepływu sterowania. Dlatego mój {{$last ? '' : ', '}}nie działa.

Czy istnieje alternatywny sposób tworzenia list oddzielonych przecinkami?

EDYCJA 1
jest coś prostszego niż:

<span ng-show="!$last">, </span>
Franck Freiburger
źródło
5
Zawsze możesz używać CSS do formatowania list w ten sposób (wtedy nie musisz modyfikować HTML, kiedy szef chce ich w osobnych liniach itp.) - patrz stackoverflow.com/questions/1517220/…
AlexFoxGill

Odpowiedzi:

338

Możesz to zrobić w ten sposób:

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

..Ale podoba mi się odpowiedź Filipa :-)

Andrew Joslin
źródło
Nie ($last && '' || ', ')zawsze powinno ustępować ', '?
okm
15
Podobnie jak powyżej, nie mogłem uzyskać kątowej poprawnej oceny $ last na true lub false w szablonie. Kiedyś to: {{{true: '', false: ', '}[$last]}}. Ta technika jest bardziej elastyczna niż używanie, .joinponieważ pozwala elementom na liście być członkami tablicy, na przykład:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus
3
Zaktualizowano, aby używać operatorów trójskładnikowych
Andrew Joslin,
1
Jak mogę wstawić i wydrukować tablicę, aby moja tablica wyglądała tak: John, Mike i Nil. Jak uzyskać ten format bez korzystania z dyrektywy.
MaTya
Korzystam z tego podejścia, ponieważ pozwala mi to zastosować filtr do każdej wartości na liście.
C Fairweather,
231

Wystarczy użyć wbudowanej join(separator)funkcji JavaScript dla tablic:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Philipp Reichart
źródło
21
Jeśli chcesz separatorów HTML, prawdopodobnie czas na dyrektywę zapisu . Możesz także wstawiać HTML join()i wyłączać funkcję ucieczki HTML, ale jest w tym specjalne miejsce w piekle;)
Philipp Reichart
Fajnie, nawet nie myślałem o tym, aby używać go w ten sposób.
Strawberry
@DavidKEgghead Zaczynam się różnić, jsfiddle.net/wuZRA . Jak to dla ciebie nie działa?
Philipp Reichart
2
@PhilippReichart przepraszam za opóźnienie. Oto przykład: jsfiddle.net/Sek8F - wygląda na to, że celujesz w ciąg znaków, w którym, jak mam na myśli, obiekt.
Ravi Ram
101

Również:

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

I w szablonie:

{{ itemsArray | joinBy:',' }}
sanusart
źródło
11
Ta odpowiedź pokazuje „drogę kątową” i powinna być oznaczona jako najlepsza.
Eugene Griaznov
14
Dlaczego nie zapisać sześciu linii i po prostu zrobić {{ itemsArray.join(', ') }}?
Philipp Reichart
12
Nie jestem pewien, czy ponowne pisanie podstawowych funkcji JavaScript w AngularJS jest naprawdę „Angularowym sposobem” ...
Michael Cole
1
Ta odpowiedź pokazuje, w jaki sposób Angular może zwiększyć wartość tablic obiektów
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
źródło
1
Wydaje się to najbardziej „semantyczne”, ponieważ wybór listy rozdzielanej przecinkami dotyczy wyłącznie prezentacji. Równie dobrze mogłaby to być podlista.
Elliot Cameron
To było pierwsze rozwiązanie, jakie przyszło mi do głowy. Mniej zależny od JavaScript.
Kalpesh Panchal
10

Możesz także użyć CSS, aby to naprawić

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

Ale odpowiedź Andy'ego Joslina jest najlepsza

Edycja: Zmieniłem zdanie, musiałem to zrobić niedawno i ostatecznie zdecydowałem się na filtr sprzężenia.

Chris Stephens
źródło
2
Wybrałbym też niestandardowy filtr, ale podoba mi się twój pomysł :)
JBC
5

Myślę, że lepiej jest używać ng-if. ng-showtworzy element w domi ustawia go display:none. Im więcej domelementów, tym więcej zasobów staje się głodnych, a na urządzeniach z niższymi zasobami, im mniej domelementów, tym lepiej.

TBH <span ng-if="!$last">, </span>wydaje się świetnym sposobem na zrobienie tego. To proste.

the7erm
źródło
Podoba mi się to podejście, ponieważ jest proste i nadal obsługuje separatory oparte na HTML. Dzięki @ the7erm!
alexkb
2

Ponieważ to pytanie jest dość stare i od tego czasu AngularJS miał czas na ewolucję, można to teraz łatwo osiągnąć za pomocą:

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

Zauważ, że używam ngBindzamiast interpolacji, {{ }}ponieważ jest znacznie wydajniejszy: ngBind będzie działał tylko wtedy, gdy przekazana wartość faktycznie się zmieni. Z kolei nawiasy klamrowe {{ }}będą sprawdzane i odświeżane przy każdym $ streszczeniu, nawet jeśli nie jest to konieczne. Źródło: tutaj , tutaj i tutaj .

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>

Podsumowując, wszystkie rozwiązania tutaj działają i obowiązują do dziś. Naprawdę jestem przekonany do tych, które dotyczą CSS, ponieważ jest to bardziej problem z prezentacją.

Cosmin Ababei
źródło
1

Lubię podejście Simbu, ale nie jest mi wygodnie korzystać z pierwszego dziecka lub ostatniego dziecka. Zamiast tego modyfikuję tylko zawartość powtarzającej się klasy przecinek list.

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

Jeśli używasz ng-show do ograniczenia wartości, {{$last ? '' : ', '}}nie zadziała, ponieważ nadal będzie uwzględniał wszystkie wartości.

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

Powoduje dodanie przecinka po wartości „ostatniej” , ponieważ w przypadku ng-show nadal uwzględnia wszystkie 4 wartości

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

Jednym z rozwiązań jest dodanie filtra bezpośrednio do powtórzenia ng

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

Wyniki

{"email":"1"},
{"email":"1"}
Mihai
źródło
Wszelkie sugestie, jak rozwiązać ten problem w Angular 2 bez tworzenia niestandardowej potoku?
chaenu