68

I want to create a list of items in my template, separated by commas, but I don't want the last item to have a comma:

one, two, three

How do I accomplish this with Angular 2's template syntax?

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492

3 Answers3

180

I like Eric's answer better (see his comment for a sample Plunker):

<span *ngFor="let item of items; let isLast=last">
   {{item}}{{isLast ? '' : ', '}}
</span>

My original answer was to use the optional index in the NgFor microsyntax:

<span *ngFor="#item of items, #i=index">
   {{item}}{{i === items.length - 1 ? '' : ', '}}
</span>

An alternative is to use just use CSS ::before syntax, as described here: https://stackoverflow.com/a/31805688/215945

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
42

I think a simpler approach is

<span> {{items.join(", ")}} </span>
nik
  • 2,455
  • 21
  • 26
  • in case you need to surround each string with a character, for example the double quotes, you can use: ` "{{ items.join('", "') }}" ` – Francesco Borzi Sep 26 '17 at 16:34
  • 1
    It didn't work for me when I used this solution in combination with overriding the toString() method of my custom object. But it's indeed the shortest solution for primitive types. – Glenn Van Schil Jan 04 '18 at 13:52
  • 1
    How do you insert a pipe in here if you need to transform items using pipe (e.g. array of price objects like `[{amount: 1, currency: 'USD'}, {amount: 2, currency: 'GBP'}]` to `$1, £2`? – izogfif May 12 '18 at 12:23
  • @izogfif You should create another stackoverflow question and maybe post the link here. Without going into detail, use javascript to build out the string. You don't have to pipe within the `{{ }}`. – christo8989 Jan 17 '19 at 21:02
  • tried doing it this way and if repeats my entire array `test: string[]= ['apple', 'banna', 'mango', 'orange', 'pear']; span *ngFor="let fruit of test">{{test.join(", ")}}` produces: apple, banna, mango, orange, pearapple, banna, mango, orange, pearapple, banna, mango, orange, pearapple, banna, mango, orange, pearapple, banna, mango, orange, pear L – Flash Mar 14 '19 at 13:27
  • I guess you don't need to use ngFor .. Just {{test.join(",")}} woud do – nik Mar 14 '19 at 13:34
  • Good solution, but it doesn't show how to do this _with_ ngFor. And in my case, I need to do this only with ngFor. – Maksym Ovsianikov May 21 '19 at 19:17
  • I think you should avoid function calls in a template as it slows down rendering. That is why the ngFor solution is and should be accepted as the best answer. – Filip Matys Jun 07 '19 at 13:00
  • One problem with this is that you can't include html in your items, for example, having them be links. – clahey Dec 21 '20 at 06:19
0

I have just needed todo this but my value is in an attribute so the marked answer did not work.

Someone may find this helpful :

I used a pipe, I could have built the string up but felt a pipe would be more readable

CLI

ng g p Delimiter

Pipe

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'delimiter'
})
export class DelimiterPipe implements PipeTransform {
  transform(value: string, delimiter: string, isLast: boolean)  {
    return !isLast ? value + delimiter : value;
  }
}

View

<div ngFor="let item of items; let isLast=last" 
     [innerHtml]="item | delimiter:', ':isLast">
</div>

I needed some html in my view hence my need to use the attribute, eg

<div ngFor="let item of items; let isLast=last" 
     [innerHtml]="item | safeHtml | delimiter:', ':isLast">
</div>
Steve Drake
  • 1,968
  • 2
  • 19
  • 41