0

I want to generate comma separated string from an array.

This is my data:

responseData= [{ name: 'Some Data 1', type:'action' }, 
               { name: 'Some Data 2', type:'action' },
               { name: 'Data 3', type:'NA' }, 
               { name: 'Data 4', type:'action' },
               { name: 'Data 5', type:'NA' }];

This is how I'm looping. I only want to loop through action type.

<div *ngFor="let data of responseData; let last=last">
    <div *ngIf="data.type=='action'">
        {{ data.name}} {{last?'':', '}}
    </div>
</div>

But I'm left with another comma at last. How do I remove that?

Any help would be much appreciated. Thanks!

Dungeon
  • 972
  • 2
  • 16
  • 32

5 Answers5

4

The reason last is not getting applied is because the last element is not of the type "action".

As a Fix, You can create a custom function to filter the initial data first and apply the same logic,

<div *ngFor="let data of filterFunction(responsedata); last as isLast">
    <div >
        {{ data.name}}  {{isLast?'':', '}}
    </div>
</div>

DEMO

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
1

Since the filtering for type = action happens inside the ngForOf, the last element still not counted, so last is always false for your case.

I have added a new Array which is filtered based on type = action at the typescript and that works for me. See the example below at stackblitz.

https://stackblitz.com/edit/angular-dfhpan

javapedia.net
  • 2,531
  • 4
  • 25
  • 50
1

I would use a pipe for this:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'listify'})
export class ListifyPipe implements PipeTransform {
    transform(responseData: Array<any>, responseType: string): string {
        return responseData
            .filter(r => r.type === responseType)
            .map(r => r.name)
            .join();
    }
}

and then call it

<div>{{responseData | listify : 'action'}}</div>
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
0

You can't use the 'last' binding (which is like checking if current iteration index + 1 is equal to array length) with a visually filtered array - it will not work since the actual array index will not be affected by your filtering.

You can either filter the array before using it in your template:

responseData= [
 { name: 'Some Data 1', type:'action' }, 
 { name: 'Some Data 2', type:'action' },
 { name: 'Data 3', type:'NA' }, 
 { name: 'Data 4', type:'action' },
 { name: 'Data 5', type:'NA' }
]
.filter(item => item.type === 'action');

Then, use it in your template without filtering

<div *ngFor="let data of responseData; let last=last">
    {{ data.name}} {{last?'':', '}}
</div>

...or, better, create a custom pipe which will filter the array and keep proper tracking of the 'last' binding

There are many examples so I will not provide another copy here, you will just need to use it as

...*ngFor="let item of myArray | myFilter;let last...
alou
  • 1,432
  • 13
  • 16
0

You can add a conditional comma before each item value like:

<ng-container *ngFor="let item of list; let i = index">  
   <span *ngIf="i > 0">, </span><span> {{ item.value }} </span>
</ng-container>

or

<ng-container *ngFor="let item of list; let i = index">  
  {{ i > 0 ? ', ': '' }} {{ item.value }}
</ng-container>