Search code examples
arraysangularangular-ng-if

How to Use *ngIf to create break points in when display an array of objects in a list?


I have an array of objects (cars in this example) that I sort using a simple sort function. I would like to display a Title in the list for each new type of car is being displayed. I think I should *ngIf somehow, but can't seem to figure out how.

Expected output:

Asian Cars:

  • KIA
  • Toyota

Cseh Cars

  • Skoda
  • ... and so on

Her is what I have so far:

export class AppComponent {
  items = [
    {"car":"BMW", "type":"German Cars"},
    {"car":"Kia", "type":"Asian Cars"},
    {"car":"Mercedes", "type":"German Cars"},
    {"car":"Audi", "type":"German Cars"},
    {"car":"Seat", "type":"Spanish Cars"},
    {"car":"Skoda", "type":"Cseh Cars"},
    {"car":"Trabant", "type":"East-German Cars"},
    {"car":"Wardburg", "type":"East-German Cars"},
    {"car":"Toyota", "type":"Asian Cars"},
];

sortedItems = this.items.sort((a,b) => (a.type > b.type) ? 1: ((b.type > a.type) ? -1 :0));
}

an in HTML

   <div>
  <ul>
    <li *ngFor = "let item of sortedItems">
      {{item.car}}
      {{item.type}}
    </li>
  </ul>
</div>

Solution

  • You should massage your data a bit more. A Map is a good type for this. You will use the "type" of the vehicle as the key, and the value will be an array of the vehicles for that type.

    Here's an example on stack blitz to get you started: https://stackblitz.com/edit/angular-md2ltf?file=src%2Fapp%2Fapp.component.ts

    Updated component example

    items = [
        {"car":"BMW", "type":"German Cars"},
        {"car":"Kia", "type":"Asian Cars"},
        {"car":"Mercedes", "type":"German Cars"},
        {"car":"Audi", "type":"German Cars"},
        {"car":"Seat", "type":"Spanish Cars"},
        {"car":"Skoda", "type":"Cseh Cars"},
        {"car":"Trabant", "type":"East-German Cars"},
        {"car":"Wardburg", "type":"East-German Cars"},
        {"car":"Toyota", "type":"Asian Cars"},
    ];
    
    mappedItems = new Map<string, string[]>();
    
    ngOnInit() {
      this.items.forEach(item => {
        let existingType = this.mappedItems.get(item.type) || [];
        this.mappedItems.set(item.type, [...existingType, item.car])
      })
    }
    

    Updated template (note the use of the built in Angular "keyvalue" pipe)

    <ng-container *ngFor="let item of mappedItems | keyvalue;">
    <p>{{ item.key }}</p>
    <ul>
      <li *ngFor="let car of item.value;">
        {{ car }}
      </li>
    </ul>
    </ng-container>