1

New to stack overflow and fairly new to Angular - say intermediate level.

So I have an issue where I'm using an *ngFor loop to create and populate the first three columns of an HTML table, I then want to use a separate *ngFor condition to loop through a collection of documents from a firestore database to populate the rows of the table where a certain condition is met until the last column where I would like an if condition applied to apply one of two options for the content.

Confusing to describe with just words so here's some code to paint a better picture:

The JSON used to create the HTML table:

tables: any [] = [
    {
      'time': 1200,
      'number': 1,
      'covers': 2
    },
    {
      'time': 1200,
      'number': 2,
      'covers': 2
    },
    {
      'time': 1200,
      'number': 3,
      'covers': 2
    },
    {
      'time': 1230,
      'number': 1,
      'covers': 2
    },
    {
      'time': 1230,
      'number': 2,
      'covers': 2
    },
    {
      'time': 1230,
      'number': 3,
      'covers': 2
    },
    {
      'time': 1300,
      'number': 3,
      'covers': 2
    },
    {
      'time': 1300,
      'number': 1,
      'covers': 2
    },
    {
      'time': 1300,
      'number': 2,
      'covers': 2
    },
    {
      'time': 1300,
      'number': 3,
      'covers': 2
    }
    ];

The HTML table where filteredReservations is the array of the collection of documents returned by a firestore get request:

    <table class="table">
            <thead>
            <th>Time</th>
            <th>Table</th>
            <th>Covers</th>
            <th>Name</th>
            <th>Contact</th>
            <th>Created By</th>
            <th>Status</th>
            <th>Actions</th>
            </thead>
            <tbody>
            <tr *ngFor="let table of tables">
              <td>{{table.time}}</td>
              <td>{{table.number}}</td>
              <ng-container *ngFor="let reservation of filteredReservations">
            <ng-container *ngIf="table.time == reservation.time && table.number == reservation.table">
              <td>{{reservation.covers}}</td>
              <td>{{reservation.name}}</td>
              <td>{{reservation.contact}}</td>
              <td>{{reservation.createdBy}}</td>
              <td>{{reservation.status}}</td>
              <ng-container>
                <td *ngIf="table.time == reservation.time && table.number == reservation.table; else empty">
                  <button mat-icon-button [routerLink]="['/new', reservation.id]">
                    <mat-icon>edit</mat-icon>
                  </button>
                </td>
              </ng-container>
            </ng-container>
          </ng-container>
            </tr>
            </tbody>
          </table>      
<ng-template #empty>
        <td>
          <button mat-icon-button [routerLink]="['/new']">
            <mat-icon>edit</mat-icon>
          </button>
        </td>
</ng-template>

The expected result is a HTML table will be created using the first *ngFor, the filteredReservations will appear in rows where the condition is met and the last column will display an edit icon that will link to either add a new reservation or edit the existing where the condition is met.

When I try to achieve what I'm aiming for the last column repeats as many times as there are documents in the collection i.e. i need the last columns to be outside the filteredReservations loop but still use the reservation data to check the if condition.

What I'm aiming for:1

What I'm currently getting:2

I've tried to explain as best as possible so hopefully this makes sense.

  • 1
    It would help a lot if you could provide a plunkr – Arif Feb 26 '19 at 13:40
  • It seems to me like this would involve some very complicated logic to keep this data as-is. You might consider transforming the format of this data by creating some kind of "group by" pipe (there are many examples online) where you can group each table by reservation, then ngFor reservations -> ngFor tables per reservation. That seems to be what you're getting at if I understand correctly. – Zircon Feb 26 '19 at 13:45
  • I would aim for `{{reservation.covers}}` for all columns – Swoox Feb 26 '19 at 14:23

1 Answers1

0

I wouldn't do the iteration within the html. Prefer doing this within component.ts:

 <tbody>
  <tr *ngFor="let table of tables" >
    <td>{{table.time}}</td>
    <td>{{table.number}}</td>
    <ng-template let-reservation="findReservation(table)">
      <td>{{reservation.covers}}</td>
      <td>{{reservation.name}}</td>
      <td>{{reservation.contact}}</td>
      <td>{{reservation.createdBy}}</td>
      <td>{{reservation.status}}</td>
      <td *ngIf="reservation">
        <button mat-icon-button [routerLink]="['/new', reservation.id]">
          <mat-icon>edit</mat-icon>
        </button>
      </td>
    </ng-template>    
  </tr>
</tbody>

And

findReservation(table: Table): Reservation {
  return this.filteredReservations.find(reservation => {/*your check*/})
}
MoxxiManagarm
  • 8,735
  • 3
  • 14
  • 43