【问题标题】:change the number of columns in mat-grid-list when the component first loads首次加载组件时更改 mat-grid-list 中的列数
【发布时间】:2021-05-28 07:30:11
【问题描述】:

我正在实现一个 mat-grid-list 图像,并且我正在根据屏幕大小动态更改列数。这很好用,除非当它第一次加载时它被设置为 3 列而不管屏幕大小,直到事件发生。因此,如果您导航到不同的组件并返回,您将再次看到 3 列。 我尝试向构造函数或其他生命周期钩子添加一些代码但没有成功,但这可能只是我没有正确实现它。在 typescript 文件中,products 对象数组、构造函数和 ngOnInit() 钩子不相关。第一张图片是它加载时的样子,因为它默认为 3,第二张图片是我点击某些东西或调整屏幕大小时的样子,第二张图片就是它应该看起来的样子。您会注意到,在打字稿文件中,我将默认行数设置为 3,但如果我将其删除,则会出现错误。也欢迎对设计提出任何反馈。

 <!-- html -->
<div #gridView>
    <mat-grid-list cols="{{columnNum}}" gutterSize="5rem" rowHeight="25rem">
        <mat-grid-tile *ngFor="let product of products">
            <img src="{{ product.image }}" alt="">
        </mat-grid-tile>
    </mat-grid-list>
</div>

打字稿文件

import { AfterViewInit, Component, HostListener, OnInit, ViewChild } from '@angular/core';
import { ProductsService } from '../services/products.service';

@Component({
  selector: 'app-gallery',
  templateUrl: './gallery.component.html',
  styleUrls: ['./gallery.component.css']
})
export class GalleryComponent implements OnInit, AfterViewInit {
  products : {name: string, productId: string, image: string, price: number, desc: string, size: string, isPrintAvailable: boolean}[] = [];
  @ViewChild('gridView') gridView: any;
  columnNum = 3; //initial count
  tileSize = 450; //one tile should have this width

  setColNum(){
     let width = this.gridView.nativeElement.offsetWidth;
     this.columnNum = Math.trunc(width/this.tileSize);
   }

   //calculating upon loading
   ngAfterViewInit() {
     this.setColNum();
   }

   //recalculating upon browser window resize
   @HostListener('window:resize', ['$event'])
   onResize() {
     this.setColNum();
   }

  constructor(private productService: ProductsService) {}

  ngOnInit(): void {
    this.products = this.productService.getProducts();
  }

}

加载时的样子

点击或调整屏幕大小等事件后的外观(如果我离开并返回它会返回顶部图像)

【问题讨论】:

    标签: javascript css angular typescript angular-material


    【解决方案1】:

    在逐页阅读之后,我找到了一个不需要弄乱打字稿文件并且可以完美运行的解决方案。基本上,您创建一个指令来替换 cols 属性,其余的由指令完成。我将添加mat-grid-list 标记的代码以及directive 的代码,但这是页面,以便我可以感谢作者https://www.mymiller.name/wordpress/programming/angular-material-grid-layout-responsive/

    html

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

    指令

    import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
    import { Directive, Input, OnInit } from '@angular/core';
    import { MatGridList } from '@angular/material/grid-list';
    
    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;
          }
        });
      }
    }
    

    【讨论】:

      【解决方案2】:

      问题是首先您将 columnNum 设为 3,然后它将根据您的窗口大小而变化。问题是,如果您立即更改大小,则会收到 ExpressionChangedAfterItHasBeenCheckedError,因此您需要一些时间来更改 columnNum 有一些方法可以解决此问题,其中一种方法是使用 set timeout 函数或使用 cdr.detectChanges()

      setColNum() {
          let width = this.gridView.nativeElement.offsetWidth;
          setTimeout(() => {
            this.columnNum = Math.trunc(width / this.tileSize);
          }, 0);
        }
      

      constructor(private cdr: ChangeDetectorRef) {}
      ngAfterViewInit() {
          this.setColNum();
          this.cdr.detectChanges();
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-01
        • 2018-10-19
        • 2016-10-08
        • 2019-09-04
        • 2018-01-05
        • 2020-04-09
        • 1970-01-01
        • 2021-10-31
        相关资源
        最近更新 更多