Verwenden von Komma als Listentrennzeichen bei AngularJS

179

Ich muss eine durch Kommas getrennte Liste von Elementen erstellen:

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

Gemäß der AngularJS-Dokumentation sind in Ausdrücken keine Kontrollflussanweisungen zulässig. Deshalb {{$last ? '' : ', '}}funktioniert mein nicht.

Gibt es eine alternative Möglichkeit, durch Kommas getrennte Listen zu erstellen?

EDIT 1
gibt es etwas einfacher als:

<span ng-show="!$last">, </span>
Franck Freiburger
quelle
5
Sie können CSS immer verwenden, um Listen auf diese Weise zu formatieren (dann müssen Sie HTML nicht ändern, wenn Ihr Chef sie in separaten Zeilen usw. haben möchte) - siehe stackoverflow.com/questions/1517220/…
AlexFoxGill

Antworten:

337

Sie könnten es so machen:

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

..Aber ich mag Philipps Antwort :-)

Andrew Joslin
quelle
Sollte nicht ($last && '' || ', ')immer nachgeben ', '?
Ok,
15
Wie oben, ich konnte keinen Winkel bekommen, um $ last innerhalb einer Vorlage richtig als wahr oder falsch zu bewerten. Ich habe das benutzt : {{{true: '', false: ', '}[$last]}}. Diese Technik ist flexibler als die Verwendung, .joinda die Elemente in der Liste jeweils Mitglieder eines Arrays sein können, z. B.:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus,
3
Aktualisiert, um ternäre Operatoren zu verwenden
Andrew Joslin
1
Wie kann ich und in das gedruckte Array einfügen, damit mein Array so aussieht: John, Mike und Nil. So erhalten Sie dieses Format ohne Verwendung der Direktive.
MaTya
Ich verwende diesen Ansatz, da ich damit für jeden Wert in der Liste einen Filter verwenden kann.
C Fairweather
231

Verwenden Sie einfach das integrierte Javascript join(separator) Funktion für Arrays:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Philipp Reichart
quelle
21
Wenn Sie HTML-ish Separatoren wollen ist es wahrscheinlich Zeit zu einer Schreib Richtlinie . Sie könnten auch HTML in join()HTML
Philipp Reichart
Schön, ich habe nicht einmal darüber nachgedacht, es so zu benutzen.
Erdbeere
@ DavidKEgghead Ich bitte um Unterschied, jsfiddle.net/wuZRA . Wie funktioniert das bei dir nicht?
Philipp Reichart
2
@PhilippReichart Entschuldigung für die Verzögerung. Hier ein Beispiel: jsfiddle.net/Sek8F - Sieht so aus, als würden Sie auf eine Zeichenfolge abzielen, bei der ich mich auf ein Objekt beziehe.
Ravi Ram
101

Ebenfalls:

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

Und in Vorlage:

{{ itemsArray | joinBy:',' }}
Sanusart
quelle
11
Diese Antwort zeigt "Winkelweg" und sollte als die beste markiert werden.
Eugene Griaznov
14
Warum nicht sechs Zeilen speichern und einfach tun {{ itemsArray.join(', ') }}?
Philipp Reichart
12
Ich bin nicht sicher, ob das Umschreiben von JavaScript-Kernfunktionen in AngularJS wirklich "der Angular-Weg" ist ...
Michael Cole
1
Diese Antwort zeigt, wie Angular einen Mehrwert für Arrays von Objekten schaffen kann
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
quelle
1
Dies scheint der "semantischste" Weg zu sein, da die Wahl der Verwendung einer durch Kommas getrennten Liste ausschließlich die Präsentation betrifft. Es hätte genauso gut eine Unterliste sein können.
Elliot Cameron
Dies war die erste Lösung, die mir in den Sinn kam. Weniger abhängig von JavaScript.
Kalpesh Panchal
10

Sie können auch CSS verwenden, um das Problem zu beheben

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

Aber Andy Joslins Antwort ist am besten

Bearbeiten: Ich habe meine Meinung geändert, dass ich dies kürzlich tun musste, und am Ende habe ich einen Join-Filter verwendet.

Chris Stephens
quelle
2
Ich würde auch für einen benutzerdefinierten Filter gehen, aber ich mag Ihre Idee :)
JBC
5

Ich denke, es ist besser zu verwenden ng-if. ng-showerstellt ein Element in der domund setzt es display:none. Je mehr domElemente Sie haben, desto ressourcenhungriger wird Ihre App. Auf Geräten mit geringeren Ressourcen gilt: Je weniger Elemente, desto dombesser.

TBH <span ng-if="!$last">, </span>scheint eine großartige Möglichkeit zu sein. Es ist einfach.

the7erm
quelle
Ich mag diesen Ansatz, da er einfach ist und immer noch HTML-basierte Trennzeichen unterstützt. Danke @ the7erm!
Alexkb
2

Da diese Frage ziemlich alt ist und AngularJS seitdem Zeit hatte, sich weiterzuentwickeln, kann dies jetzt leicht erreicht werden mit:

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

Beachten Sie, dass ich ngBindanstelle der Interpolation verwende, {{ }}da diese viel leistungsfähiger ist: ngBind Wird nur ausgeführt, wenn sich der übergebene Wert tatsächlich ändert. Die Klammern {{ }}hingegen werden bei jedem $ Digest schmutzig überprüft und aktualisiert, auch wenn dies nicht erforderlich ist. Quelle: hier , hier und hier .

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>

Abschließend ist festzuhalten, dass alle hier aufgeführten Lösungen funktionieren und bis heute gültig sind. Ich bin wirklich zu denen gefunden, die CSS betreffen, da dies eher ein Präsentationsproblem ist.

Cosmin Ababei
quelle
1

Ich mag den Ansatz von simbu, aber es ist mir nicht angenehm, das erste oder letzte Kind zu verwenden. Stattdessen ändere ich nur den Inhalt einer sich wiederholenden Liste-Komma-Klasse.

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

Wenn Sie ng-show verwenden, um die Werte zu begrenzen, {{$last ? '' : ', '}}funktioniert dies nicht, da weiterhin alle Werte berücksichtigt werden. Beispiel

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

Das Hinzufügen eines Kommas nach dem "letzten" Wert führt dazu , dass bei ng-show immer noch alle 4 Werte berücksichtigt werden

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

Eine Lösung besteht darin, einen Filter direkt in ng-repeat hinzuzufügen

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

Ergebnisse

{"email":"1"},
{"email":"1"}
Mihai
quelle
Gibt es Vorschläge, wie Sie dieses Problem in Angular 2 auf die gleiche Weise lösen können, ohne eine benutzerdefinierte Pipe zu erstellen?
Chaenu