Angular 5 Mat-grid list responsive

后端 未结 6 1686
灰色年华
灰色年华 2021-01-30 03:08

i created grid list with column 6 and i want to be grid title take 100% width on small screen devices. Now it creates 6 column on small screens as well

Expected: One gri

相关标签:
6条回答
  • 2021-01-30 03:41

    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;
        });
      }
    }

    0 讨论(0)
  • 2021-01-30 03:41

    I used a BreakpointObserver to achieve this.

    See angular documentation : https://material.angular.io/cdk/layout/overview

    import { Component, OnInit} from '@angular/core';
    import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
    
    
    @Component({
      selector: 'app-index',
      templateUrl: './index.component.html',
      styleUrls: ['./index.component.css']
    })
    export class IndexComponent implements OnInit {
    
      cols : number;
    
      gridByBreakpoint = {
        xl: 3,
        lg: 3,
        md: 3,
        sm: 2,
        xs: 1
      }
    
      constructor(private breakpointObserver: BreakpointObserver) {
        this.breakpointObserver.observe([
          Breakpoints.XSmall,
          Breakpoints.Small,
          Breakpoints.Medium,
          Breakpoints.Large,
          Breakpoints.XLarge,
        ]).subscribe(result => {
          if (result.matches) {
            if (result.breakpoints[Breakpoints.XSmall]) {
              this.cols = this.gridByBreakpoint.xs;
            }
            if (result.breakpoints[Breakpoints.Small]) {
              this.cols = this.gridByBreakpoint.sm;
            }
            if (result.breakpoints[Breakpoints.Medium]) {
              this.cols = this.gridByBreakpoint.md;
            }
            if (result.breakpoints[Breakpoints.Large]) {
              this.cols = this.gridByBreakpoint.lg;
            }
            if (result.breakpoints[Breakpoints.XLarge]) {
              this.cols = this.gridByBreakpoint.xl;
            }
          }
        });
      }
    
      ngOnInit() {
      }
      
    }
    <mat-grid-list #grid [cols]="cols" rowHeight="20:11" gutterSize="20px" >
      <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>

    0 讨论(0)
  • 2021-01-30 03:43

    Great work everybody!

    I made some further improvements to Алексей Сердюков's Answer:

    • updated for flex-layout 7.0.0+
    • when resizing the window, the directive under some circumstances returned the wrong count

    Gist @ GitHub: https://gist.github.com/mzellho/7fc7d5bd52a29948c47911a993547dad

    0 讨论(0)
  • 2021-01-30 03:47

    Addition to the @Leo Caserio' s answer, if you get an error on the first load as follows:

    Error: mat-grid-list: must pass in number of columns. Example: ...

    You can use subject:

    Component

    @ViewChild('grid',{static:true}) grid: MatGridList;
    cols:Subject<any> = new Subject();
    
    constructor(private observableMedia: MediaObserver) { }
    
    ngAfterContentInit() {
        this.observableMedia.asObservable().subscribe((change: MediaChange[]) => {
          this.cols.next(this.gridByBreakpoint[change[0].mqAlias]);
        });
      }
    

    Template

    <mat-grid-list #grid [cols]="cols | async"  rowHeight = "1:1">
    

    Note: @angular/flex-layout": {"version": "8.0.0-beta.26" }

    0 讨论(0)
  • 2021-01-30 03:48

    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!

    0 讨论(0)
  • 2021-01-30 03:54

    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

    0 讨论(0)
提交回复
热议问题