具有不同高度的子行(嵌套单元)的Angular Material表 [英] Angular Material table with subrows (nested cells) of different heights

查看:65
本文介绍了具有不同高度的子行(嵌套单元)的Angular Material表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个表格,其中包含模拟子行的嵌套单元格.如果每个单元格的内容不超过嵌套单元格(A)的min-height属性值,则该方法工作正常.

不幸的是,当该值超过时,表会崩溃(B).是否有任何简单*的方法来正确对齐嵌套单元格以获得像(C)这样的表?

代码: https://stackblitz.com/edit/angular-aejwfm

(*)我知道我们可以使用javascript将代表某个子行的所有单元格的高度设置为max(该子行中所有单元格的高度),但是我更喜欢纯HTML/CSS/Angular解决方案.

解决方案

一个可能的解决方案是,您可以创建一个指令,该指令为每行查找一个具有max-height的单元格,并将相同的高度应用于该行的所有单元格.

但是您正在渲染数据列VISE,因此您需要向指令提供一些信息,指令可以使用这些信息来标识单个行的单元格.

我已经更新了您的代码以获得所需的结果.

https://stackblitz.com/edit/angular-aejwfm-6htvuk

这是我对您的演示所做的更改的简要说明:

创建一个指令,该指令接受book对象作为输入.本书的对象将帮助我们识别单行的单元格.

@Directive({
  selector: '[matchCellHeight]'
})
export class MatchCellHeightDirective {

  @Input() matchCellHeight: any;

  constructor(private el: ElementRef) { 

  }
}

然后将此指令绑定到模板中的每个单元格元素.

    <ng-container matColumnDef="title">
      <mat-header-cell *matHeaderCellDef> Title </mat-header-cell>
      <mat-cell *matCellDef="let genre">
        <mat-cell [matchCellHeight]='book' *ngFor="let book of genre.books"> //bind matchCellHeight to each cell
           {{book.title}} 
        </mat-cell>
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="pages">
      <mat-header-cell *matHeaderCellDef> Pages </mat-header-cell>
      <mat-cell *matCellDef="let genre">
        <mat-cell [matchCellHeight]='book' *ngFor="let book of genre.books">
           {{book.pages}} 
        </mat-cell>
      </mat-cell>
    </ng-container>

现在,我们需要将每个单元格的引用存储在某个位置,以便我们可以在每个单元格上应用匹配高度逻辑.为此,我创建了一个服务并将其注入指令中.

@Injectable()
export class MatchCellHeightService{
  cells:{el:ElementRef,data:any}[] = [];
  constructor(){

  }

  findUniqueBooks():any[]{
    return this.cells.map(currCell => currCell.data).reduce(
      (acc,curr) => {
        if(acc){
          if(acc.indexOf(curr) == -1){
            acc.push(curr);
          }
        }else{
          acc = [].push(curr)
        }
        return acc;
      },[]
    )
  }

  matchHeight(){
    /* first find all the unique books*/
    let books = this.findUniqueBooks();


    for(let i = 0; i < books.length ; i++){
      let currbook = books[i];

      /*for each book find cells that containins this book object info
        (in this demo each row is containng info about one book there for we are using book object 
        to identify cells of each row)
      */
      let bookCells:{el:ElementRef,data:any}[] = [];

        for(let j = 0; j < this.cells.length ; j++){
          let currCell = this.cells[j];
          if(currCell.data == currbook){
            bookCells.push(currCell);
          }
        }

        /*once we have the array of cells which are of same row apply the match height logic*/
        bookCells.forEach(val => val.el.nativeElement.style.height = 'initial');
        let maxHeight = Math.max(...bookCells.map(val => val.el.nativeElement.offsetHeight));
        bookCells.forEach(currCell => {
          currCell.el.nativeElement.style.height = maxHeight+'px';
        })
    }
  }
}

我希望这会有所帮助.而且我还发现了另一种实现相同功能的指令实现.这是该链接. https://scotch.io/tutorials/response-equal-height-with -angular-directive

I would like to create a table with nested cells imitating subrows. It works fine if content of every cell does not exceed min-height property value of nested cell (A).

Unfortunately when this value is exceeded the table breaks down (B). Is there any simple* way to align nested cells properly to obtain table like (C)?

code: https://stackblitz.com/edit/angular-aejwfm

(*) I know that we can use javascript to set height of all cells representing certain subrow to max(heights of all cells from that subrow) but I would prefer pure HTML/CSS/Angular solution.

解决方案

One possible solution is you can create one directive that finds a cell with max-height for each row and apply the same height to all the cell of that row.

But you are rendering data column vise so you need to provide some information to the directive using which the directive can identify cells of a single row.

I have updated your code to achieve the desired result.

https://stackblitz.com/edit/angular-aejwfm-6htvuk

here is the brief explanation of the changes I have done to your demo:

create one directive which accepts the book object as Input. This book object will help us to identify cells of single row.

@Directive({
  selector: '[matchCellHeight]'
})
export class MatchCellHeightDirective {

  @Input() matchCellHeight: any;

  constructor(private el: ElementRef) { 

  }
}

then bind this directive to each cell element in your template.

    <ng-container matColumnDef="title">
      <mat-header-cell *matHeaderCellDef> Title </mat-header-cell>
      <mat-cell *matCellDef="let genre">
        <mat-cell [matchCellHeight]='book' *ngFor="let book of genre.books"> //bind matchCellHeight to each cell
           {{book.title}} 
        </mat-cell>
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="pages">
      <mat-header-cell *matHeaderCellDef> Pages </mat-header-cell>
      <mat-cell *matCellDef="let genre">
        <mat-cell [matchCellHeight]='book' *ngFor="let book of genre.books">
           {{book.pages}} 
        </mat-cell>
      </mat-cell>
    </ng-container>

Now we need to store reference of each cell somewhere so that we can apply our match height logic on each cell. for that I have created one service and injected it in the directive.

@Injectable()
export class MatchCellHeightService{
  cells:{el:ElementRef,data:any}[] = [];
  constructor(){

  }

  findUniqueBooks():any[]{
    return this.cells.map(currCell => currCell.data).reduce(
      (acc,curr) => {
        if(acc){
          if(acc.indexOf(curr) == -1){
            acc.push(curr);
          }
        }else{
          acc = [].push(curr)
        }
        return acc;
      },[]
    )
  }

  matchHeight(){
    /* first find all the unique books*/
    let books = this.findUniqueBooks();


    for(let i = 0; i < books.length ; i++){
      let currbook = books[i];

      /*for each book find cells that containins this book object info
        (in this demo each row is containng info about one book there for we are using book object 
        to identify cells of each row)
      */
      let bookCells:{el:ElementRef,data:any}[] = [];

        for(let j = 0; j < this.cells.length ; j++){
          let currCell = this.cells[j];
          if(currCell.data == currbook){
            bookCells.push(currCell);
          }
        }

        /*once we have the array of cells which are of same row apply the match height logic*/
        bookCells.forEach(val => val.el.nativeElement.style.height = 'initial');
        let maxHeight = Math.max(...bookCells.map(val => val.el.nativeElement.offsetHeight));
        bookCells.forEach(currCell => {
          currCell.el.nativeElement.style.height = maxHeight+'px';
        })
    }
  }
}

I hope this will help. And I have also found another implementation of a directive that does the same job. Here is the link for that. https://scotch.io/tutorials/responsive-equal-height-with-angular-directive

这篇关于具有不同高度的子行(嵌套单元)的Angular Material表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆