ngFor how to wrap values in div containers based on key values

I have this array in my angular app

calendarDates = [
  {"date": "2018-10-23", "day": 23, "month":10, "year":2018, "price":"2313", "date_is_valid": true},
  {"date": "2018-10-24", "day": 24, "month":10, "year":2018, "price":"2313", "date_is_valid": true},
  ...
  {"date": "2018-11-01", "day": 1, "month":11, "year":2018, "price":"2313", "date_is_valid": false},
  ...
  {"date": "2019-02-01", "day": 1, "month":12, "year":2019, "price":"2313", "date_is_valid": true}
]

My goal is to have this structure in html using the same array:

<div *ngFor='let calendarDate of calendarDates'>
  <div class='month'>
    <div class='october'>
      <p>{{getMonthName}}</p>
      <div class='date'>{{calendarDate.date}} (2018-10-23)</div>
      <div class='date'>{{calendarDate.date}} (2018-10-24)</div>
      ...
    </div>
    <div class='november'>
      <p>{{getMonthName}}</p>
      <div class='date'>{{calendarDate.date}} (2018-11-01)</div>
      ...
    </div>
    <div class='february'>
      <p>{{getMonthName}}</p>
      <div class='date'>{{calendarDate.date}} (2019-02-01)</div>
      ...
    </div>
  </div>
</div>

I can't figure out how I could filter it and what's the best way to categorized the dates by months in the html itself and wrap the dates to month div.

How can I create the month wrappers in ngIf? The values then can change during the interaction like price or date_is_valid so it needs to be the same source.

1 answer

  • answered 2018-11-08 00:38 Sunil Singh

    You can do by creating one pipe for categorization.

    pipe

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({name: 'groupBy'})
    export class GroupByPipe implements PipeTransform {
        transform(collection: Array, property: string): Array {
            if(!collection) {
                return null;
            }
    
            const groupedCollection = collection.reduce((previous, current)=> {
                if(!previous[current[property]]) {
                    previous[current[property]] = [current];
                } else {
                    previous[current[property]].push(current);
                }
    
                return previous;
            }, {});
    
            return Object.keys(groupedCollection).map(key => ({ key, value: groupedCollection[key] }));
        }
    }
    

    to under more about this pipe, visit http://www.competa.com/blog/custom-groupby-pipe-angular-4

    html

    <div *ngFor='let calendarDatesByMonth of calendarDates | groupBy:'month''>
      <div class='month >
        <div class='october'>
          <p>{{getMonthName(calendarDatesByMonth.key)}}</p> <!-- calendarDatesByMonth.key is month number -->
          <div *ngFor='let calendarDate of calendarDatesByMonth.value'  class='date'>{{calendarDate.date}} (2018-10-23)</div>
        </div>
      </div>
    </div>