John w.
John w.

Reputation: 531

Responsive mat-grid-list

I intend to use a mat-grid-list with a set of responsive cards.

My problem is that I'm having errors with the breakpoints and I can't understand.

Can anyone help me?

DEMO

ts

 cardLayout = this.breakpointObserver
    .observe([Breakpoints.Handset, Breakpoints.Tablet])
    .pipe(
      map(({ matches }) => {
        if (matches) {
          return {
            columns: 1,
            miniCard: { cols: 1, rows: 1 },
            chart: { cols: 1, rows: 2 },
            table: { cols: 1, rows: 4 },
          };
        }

        return {
          columns: 4,
          miniCard: { cols: 1, rows: 1 },
          chart: { cols: 2, rows: 2 },
          table: { cols: 4, rows: 4 },
        };
      })
    );

Error

error

Bad Breakpoint size

size

Upvotes: 0

Views: 1618

Answers (1)

TotallyNewb
TotallyNewb

Reputation: 4820

That's because you have multiple subscriptions to your observable, so the values are resolved sequentially. So when your observable emits, first subscriber (mat-grid-list) gets updated to the new layout, change detection is fired and DOM is updated. All of this happens BEFORE the mat-grid-tile gets updated, so you end up with colspans from the previous layout on children while parent has a single column.

You can use *ngIf with as syntax to store the value locally and refer to the stored value in the children elements, e.g.

<ng-container *ngIf="cardLayout | async as layout">
    <mat-grid-list [cols]="layout.columns" rowHeight="200px">
      <mat-grid-tile
        [colspan]="layout.miniCard.cols"
        [rowspan]="layout.miniCard.rows"
      >
...
      </mat-grid-tile>
    </mat-grid-list>
  </ng-container>

This allows for a single subscription (which should be more performant as well), increases readability and removes unnecessary sequential DOM updates.

Forked stackblitz here.

Upvotes: 2

Related Questions