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>

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


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>

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

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>


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.


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.


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.


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>

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

Adakah saran tentang cara mengatasi masalah ini dengan cara yang sama di Angular 2 tanpa membuat pipa kustom?
— chaenu
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.