Using comma as list separator with AngularJS

AngularjsAngularjs Ng-Repeat

Angularjs Problem Overview


I need to create a comma-separated list of items:

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

According to the AngularJS documentation, no control flow statements is allowed in expressions. This is why my {{$last ? '' : ', '}} does not work.

Is there an alternative way to create comma-separated lists?

EDIT 1
is there something simpler than:

<span ng-show="!$last">, </span>

Angularjs Solutions


Solution 1 - Angularjs

You could do it this way:

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

..But I like Philipp's answer :-)

Solution 2 - Angularjs

Just use Javascript's built-in join(separator) function for arrays:

<li ng-repeat="friend in friends">
  <b>{{friend.email.join(', ')}}</b>...
</li>

Solution 3 - Angularjs

Also:

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

And in template:

{{ itemsArray | joinBy:',' }}

Solution 4 - Angularjs

.list-comma::before {
  content: ',';
}
.list-comma:first-child::before {
  content: '';
}

<span class="list-comma" ng-repeat="destination in destinations">
                            {{destination.name}}
                        </span>

Solution 5 - Angularjs

You can use CSS to fix it too

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

But Andy Joslin's answer is best

Edit: I changed my mind I had to do this recently and I ended up going with a join filter.

Solution 6 - Angularjs

I think it's better to use ng-if. ng-show creates an element in the dom and sets it's display:none. The more dom elements you have the more resource hungry your app becomes, and on devices with lower resources the less dom elements the better.

TBH <span ng-if="!$last">, </span> seems like a great way to do it. It's simple.

Solution 7 - Angularjs

Since this question is quite old and AngularJS had had time to evolve since then, this can now be easily achieved using:

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

Note that I'm using ngBind instead of interpolation {{ }} as it's much more performant: ngBind will only run when the passed value does actually change. The brackets {{ }}, on the other hand, will be dirty checked and refreshed in every $digest, even if it's not necessary. Source: here, here and here.

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>

On a final note, all of the solutions here work and are valid to this day. I'm really found to those which involve CSS as this is more of a presentation issue.

Solution 8 - Angularjs

I like simbu's approach, but I ain't comfortable to use first-child or last-child. Instead I only modify the content of a repeating list-comma class.

.list-comma + .list-comma::before {
    content: ', ';
}

<span class="list-comma" ng-repeat="destination in destinations">
    {{destination.name}}
</span>

Solution 9 - Angularjs

If you are using ng-show to limit the values, the {{$last ? '' : ', '}} won`t work since it will still take into consideration all the values.Example

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

Results in adding a comma after the "last" value,since with ng-show it still takes into consideration all 4 values

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

One solution is to add a filter directly into ng-repeat

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

Results

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFranck FreiburgerView Question on Stackoverflow
Solution 1 - AngularjsAndrew JoslinView Answer on Stackoverflow
Solution 2 - AngularjsPhilipp ReichartView Answer on Stackoverflow
Solution 3 - AngularjssanusartView Answer on Stackoverflow
Solution 4 - AngularjssimbuView Answer on Stackoverflow
Solution 5 - AngularjsChris StephensView Answer on Stackoverflow
Solution 6 - Angularjsthe7ermView Answer on Stackoverflow
Solution 7 - AngularjsCosmin AbabeiView Answer on Stackoverflow
Solution 8 - AngularjsDurrahanView Answer on Stackoverflow
Solution 9 - AngularjsMihaiView Answer on Stackoverflow