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.