Menggunakan koma sebagai pemisah daftar dengan AngularJS

179

Saya perlu membuat daftar item yang dipisahkan koma:

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

Menurut dokumentasi AngularJS, tidak ada pernyataan aliran kontrol yang diizinkan dalam ekspresi. Inilah mengapa saya {{$last ? '' : ', '}}tidak bekerja.

Apakah ada cara alternatif untuk membuat daftar yang dipisahkan koma?

EDIT 1
ada sesuatu yang lebih sederhana daripada:

<span ng-show="!$last">, </span>
Franck Freiburger
sumber
5
Anda selalu dapat menggunakan CSS untuk memformat daftar dengan cara ini (maka Anda tidak perlu memodifikasi HTML ketika atasan Anda menginginkannya pada baris terpisah dll) - lihat stackoverflow.com/questions/1517220/…
AlexFoxGill

Jawaban:

338

Anda bisa melakukannya dengan cara ini:

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

..Tapi saya suka jawaban Philipp :-)

Andrew Joslin
sumber
Bukankah seharusnya ($last && '' || ', ')selalu menghasilkan ', '?
okm
15
Seperti okm di atas, saya tidak bisa mendapatkan sudut untuk mengevaluasi dengan benar $ last to true atau false dalam templat. Saya menggunakan ini: {{{true: '', false: ', '}[$last]}}. Teknik ini lebih fleksibel daripada menggunakan .joinkarena memungkinkan elemen-elemen dalam daftar untuk masing-masing menjadi anggota array, seperti:<b ng-repeat="friend in friends">{{friend.email}}{{{true: '', false: ', '}[$last]}}</b>
Ryan Marcus
3
Diperbarui untuk menggunakan operator ternary
Andrew Joslin
1
Bagaimana saya bisa memasukkan dan dalam array yang dicetak sehingga array saya terlihat seperti ini: John, Mike dan Nil. Cara mendapatkan format ini tanpa menggunakan arahan.
MaTya
Saya menggunakan pendekatan ini karena memungkinkan saya untuk menggunakan filter pada setiap nilai dalam daftar.
C Fairweather
231

Cukup gunakan join(separator)fungsi bawaan Javascript untuk array:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>
Philipp Reichart
sumber
21
Jika Anda ingin pemisah HTML-ish, mungkin ini saatnya menulis arahan . Anda juga dapat memasukkan HTML ke dalam join()dan menonaktifkan HTML melarikan diri, tetapi ada tempat khusus di neraka untuk itu;)
Philipp Reichart
Bagus, saya bahkan tidak berpikir untuk menggunakannya dengan cara ini.
Strawberry
@ DavidvidGeadead Saya mohon berbeda, jsfiddle.net/wuZRA . Bagaimana itu tidak bekerja untuk Anda?
Philipp Reichart
2
@ PhilhippReichart maaf atas keterlambatannya. Berikut ini sebuah contoh: jsfiddle.net/Sek8F - sepertinya Anda menargetkan sebuah string di mana saya merujuk pada sebuah objek.
Ravi Ram
101

Juga:

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

Dan di templat:

{{ itemsArray | joinBy:',' }}
sanusart
sumber
11
Jawaban ini menunjukkan "sudut jalan" dan harus ditandai sebagai yang terbaik.
Eugene Griaznov
14
Mengapa tidak menyimpan enam baris dan lakukan saja {{ itemsArray.join(', ') }}?
Philipp Reichart
12
Saya tidak yakin menulis ulang fungsi inti JavaScript di AngularJS benar-benar "jalan Angular" ...
Michael Cole
1
Jawaban ini menunjukkan bagaimana Angular dapat menambah nilai untuk array objek
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
sumber
1
Ini tampaknya cara yang paling "semantik", karena pilihan menggunakan daftar yang dipisahkan oleh koma sepenuhnya tentang presentasi. Itu bisa saja menjadi sublist.
Elliot Cameron
Ini adalah solusi pertama yang muncul di benak saya. Kurang bergantung pada JavaScript.
Kalpesh Panchal
10

Anda dapat menggunakan CSS untuk memperbaikinya juga

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

Tapi jawaban Andy Joslin adalah yang terbaik

Sunting: Saya berubah pikiran, saya harus melakukan ini baru-baru ini dan akhirnya pergi dengan filter gabungan.

Chris Stephens
sumber
2
Saya akan pergi untuk filter khusus juga, tapi saya suka ide Anda :)
JBC
5

Saya pikir lebih baik digunakan ng-if. ng-showmenciptakan elemen dalam domdan menyetelnya display:none. Semakin banyak domelemen yang Anda habiskan, semakin banyak sumber daya yang dihabiskan aplikasi Anda, dan pada perangkat dengan sumber daya yang lebih rendah semakin sedikitdom elemen yang lebih baik.

TBH <span ng-if="!$last">, </span>sepertinya cara yang bagus untuk melakukannya. Itu mudah.

the7erm
sumber
Saya suka pendekatan ini, karena sederhana dan masih mendukung pemisah berbasis html. Terima kasih @ the7erm!
alexkb
2

Karena pertanyaan ini sudah cukup lama dan AngularJS memiliki waktu untuk berkembang sejak saat itu, ini sekarang dapat dengan mudah dicapai dengan menggunakan:

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

Perhatikan bahwa saya menggunakan ngBindalih-alih interpolasi {{ }}karena jauh lebih berkinerja: ngBind hanya akan berjalan ketika nilai yang diteruskan benar-benar berubah. Kurung {{ }}, di sisi lain, akan kotor diperiksa dan disegarkan setiap $ digest, bahkan jika itu tidak perlu. Sumber: sini , sini dan sini .

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>

Pada catatan akhir, semua solusi di sini berfungsi dan valid hingga hari ini. Saya benar-benar menemukan mereka yang melibatkan CSS karena ini lebih merupakan masalah presentasi.

Cosmin Ababei
sumber
1

Saya suka pendekatan simbu, tetapi saya tidak nyaman menggunakan anak pertama atau anak terakhir. Alih-alih, saya hanya memodifikasi konten kelas koma daftar berulang.

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

Jika Anda menggunakan ng-show untuk membatasi nilai, {{$last ? '' : ', '}}tidak akan berhasil karena masih akan mempertimbangkan semua nilai. Contoh

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

Hasil dalam menambahkan koma setelah nilai "terakhir" , karena dengan ng-show itu masih mempertimbangkan semua 4 nilai

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

Salah satu solusinya adalah menambahkan filter langsung ke ng-repeat

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

Hasil

{"email":"1"},
{"email":"1"}
Mihai
sumber
Adakah saran tentang cara mengatasi masalah ini dengan cara yang sama di Angular 2 tanpa membuat pipa kustom?
chaenu