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>

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 :-)


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>

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:',' }}

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>


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.


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.


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ą.


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>

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

Wszelkie sugestie, jak rozwiązać ten problem w Angular 2 bez tworzenia niestandardowej potoku?
chaenu
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.