Thu. Mar 28th, 2024

Angular Material is a powerful extension onto Angular for UI design. I personally fell in love with it before I ever used it. When I started using it I knew I would find things I would want to improve. Material Grid List is so handy to use and makes layouts excellent for use. However it’s not responsive.

<mat-grid-list cols="2" rowHeight="350px">
</mat-grid-list>

Making it responsive was something I realized I would need for my project. Looking around I found a lot of different ways people were doing it. However, none gave the flexibility that I wanted. I decided a Directive would be best that would complete the cols value for me. I had to spend some time looking up a few things but it has certainly taught me a few new things.

Below you will find my implementation of gridCols directive. You can pass in a value or you can use the default which will use the values for number of columns: {xs: 1, sm: 2, md: 4, lg: 6, xl: 8}

<mat-grid-list [gridCols] rowHeight="350px">
</mat-grid-list>

Or you can pass in a set of values to specify your own:

<mat-grid-list [gridCols]="{xs: 1, sm: 2, md: 3, lg: 4, xl: 5}" rowHeight="350px">
</mat-grid-list>

Either case you will the number of columns that your screen size dictates. Below is the implementation for gridCols:

import {Directive, Input, OnDestroy, OnInit} from '@angular/core';
import { MatGridList } from '@angular/material';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';

export interface GridColumns {
  xs: number;
  sm: number;
  md: number;
  lg: number;
  xl: number;
}
@Directive({
  selector: '[gridCols]'
})
export class GridColsDirective implements OnInit {
  private gridCols: GridColumns = {xs: 1, sm: 2, md: 4, lg: 6, xl: 8};

  public get cols(): GridColumns {
    return this.gridCols;
  }

  @Input('gridCols')
  public set cols(map: GridColumns) {
    if (map && ('object' === (typeof map))) {
      this.gridCols = map;
    }
  }

  public constructor(private grid: MatGridList, private breakpointObserver: BreakpointObserver) {
    if(this.grid != null) {
      this.grid.cols = this.gridCols.md;
    }
  }

  public ngOnInit(): void {
    if(this.grid != null) {
      this.grid.cols = this.gridCols.md;
    }
    this.breakpointObserver.observe([
      Breakpoints.XSmall,
      Breakpoints.Small,
      Breakpoints.Medium,
      Breakpoints.Large,
      Breakpoints.XLarge
    ]).subscribe(result => {

      if (result.breakpoints[Breakpoints.XSmall]) {
        this.grid.cols = this.gridCols.xs;
      }
      if (result.breakpoints[Breakpoints.Small]) {
        this.grid.cols = this.gridCols.sm;
      }
      if (result.breakpoints[Breakpoints.Medium]) {
        this.grid.cols = this.gridCols.md;
      }
      if (result.breakpoints[Breakpoints.Large]) {
        this.grid.cols = this.gridCols.lg;
      }
      if (result.breakpoints[Breakpoints.XLarge]) {
        this.grid.cols = this.gridCols.xl;
      }
    });
  }
}

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.

2 thoughts on “Angular Material Grid Layout Responsive”
  1. Eric,

    So glad to hear this helped you! Trust me I know I went through a number of approaches before I came up with this.

  2. This post saved me thank you so much.
    Went through many approaches and they all were deprecated or had bugs and this worked perfectly!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d