htmlcssangularangular-materialangular-flex-layout

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


Solution

  • 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.