Angular 5 Mat-grid List Responsive
Answer :
You have to set the cols
attribute of the mat-grid-list
dynamically depending on the screen width. You'd have to decide on which width breakpoint will the mat-grid-list
render the 1-column version.
HTML:
<mat-grid-list [cols]="breakpoint" rowHeight="2:0.5" (window:resize)="onResize($event)"> <mat-grid-tile>1</mat-grid-tile> <mat-grid-tile>2</mat-grid-tile> <mat-grid-tile>3</mat-grid-tile> <mat-grid-tile>4</mat-grid-tile> <mat-grid-tile>5</mat-grid-tile> <mat-grid-tile>6</mat-grid-tile> </mat-grid-list>
TS:
ngOnInit() { this.breakpoint = (window.innerWidth <= 400) ? 1 : 6; } onResize(event) { this.breakpoint = (event.target.innerWidth <= 400) ? 1 : 6; }
Stackblitz demo here
Hope this helps!
I liked Altus answer, but I would like to have more breakpoints. So I've created a simple method with some breakpoints using FlexLayout ObservableMedia service instead of onResize:
import { AfterContentInit, Component, ViewChild } from '@angular/core'; import { MediaChange, ObservableMedia } from '@angular/flex-layout'; import { MatGridList } from '@angular/material'; @Component({ selector: 'app-grid', templateUrl: './grid.component.html', styleUrls: ['./grid.component.css'] }) export class GridComponent implements AfterContentInit { @ViewChild('grid') grid: MatGridList; gridByBreakpoint = { xl: 8, lg: 6, md: 4, sm: 2, xs: 1 } constructor(private observableMedia: ObservableMedia) {} ngAfterContentInit() { this.observableMedia.asObservable().subscribe((change: MediaChange) => { this.grid.cols = this.gridByBreakpoint[change.mqAlias]; }); } }
<span>Breakpoint: {{grid.cols}}</span> <mat-grid-list #grid rowHeight="2:1"> <mat-grid-tile>1</mat-grid-tile> <mat-grid-tile>2</mat-grid-tile> <mat-grid-tile>3</mat-grid-tile> <mat-grid-tile>4</mat-grid-tile> <mat-grid-tile>5</mat-grid-tile> <mat-grid-tile>6</mat-grid-tile> <mat-grid-tile>7</mat-grid-tile> <mat-grid-tile>8</mat-grid-tile> </mat-grid-list>
See https://stackblitz.com/edit/angular-responsive-material-grid-leocaseiro
You may use the following directive if you need a reusable solution:
import { Directive, Input, OnInit } from '@angular/core'; import { MatGridList } from '@angular/material'; import { ObservableMedia, MediaChange } from '@angular/flex-layout'; export interface IResponsiveColumnsMap { xs?: number; sm?: number; md?: number; lg?: number; xl?: number; } // Usage: <mat-grid-list [responsiveCols]="{xs: 2, sm: 2, md: 4, lg: 6, xl: 8}"> @Directive({ selector: '[responsiveCols]' }) export class ResponsiveColsDirective implements OnInit { private countBySize: IResponsiveColumnsMap = {xs: 2, sm: 2, md: 4, lg: 6, xl: 8}; public get cols(): IResponsiveColumnsMap { return this.countBySize; } @Input('responsiveCols') public set cols(map: IResponsiveColumnsMap) { if (map && ('object' === (typeof map))) { this.countBySize = map; } } public constructor( private grid: MatGridList, private media: ObservableMedia ) { this.initializeColsCount(); } public ngOnInit(): void { this.initializeColsCount(); this.media.asObservable() .subscribe((changes: MediaChange) => this.grid.cols = this.countBySize[changes.mqAlias] ); } private initializeColsCount(): void { Object.keys(this.countBySize).some( (mqAlias: string): boolean => { const isActive = this.media.isActive(mqAlias); if (isActive) { this.grid.cols = this.countBySize[mqAlias]; } return isActive; }); } }
Comments
Post a Comment