RXJS loop through items and return an array

Viewed 15845

My service called "getList" returns a list of items. I want to loop through the list of items and format the date. Then return the formatted array.

My current attempt doesnt return the items in the array because I use flatMap in order to loop the items in map.

I'm using angular6 and rxjs.

My attempt:

this.list$ = this.service.getList()
      .pipe(
        flatMap(response => response.items),
        map(item => {
          item.date = moment(item.date).format('YYYY-MM-DD').toString();
          return item;
        })
      );
3 Answers

You can simply add toArray() at the end of your pipe

this.list$ = this.service.getList()
.pipe(
    mergeMap(response => response.items),
    map(item => {
        item.date = moment(item.date).format('YYYY-MM-DD').toString();
        return item;
    }),
    toArray()
)

What is probably better though is to restructure a bit your code, use the Observable map operator instead of flatMap (a.k.a. mergeMap) and inside it use the Array map method to do the formatting. In other words something like

pipe(
    map(response => response.items.map(item => {
        item.date = moment(item.date).format('YYYY-MM-DD').toString();
        return item;
    }))
)

The second approach avoids the unfolding of the Array (which in the first solution you do using flatMap) and the subsequent recreation of the Array, or at least confines this logic into the map method of Array

@Pipe({
    name: 'dateFormat'
})
export class DateFormat implements PipeTransform {
    transform(value: any, args: string[]): any {
        if (value) {
            var date = value instanceof Date ? value : new Date(value);
            return DateFormatter.format(date, 'pt', 'YYYY-MM-DD');
        }
    }
}

Use the above pipe(custome pipe) in your template

{{ date | dateFormat}}
const formatItem = item => {
  item.date = moment(item.date).format('YYYY-MM-DD').toString();
  return item;
};

this.list$ = this.service.getList()
  .pipe(
    flatMap(response => from(response.items.map(formatItem))), // returns Observable<items> from array of items
    // flatMap merges back the observables into one
    toArray()
  );
Related