Angular系列之MatTable小技巧

Posted Java码农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular系列之MatTable小技巧相关的知识,希望对你有一定的参考价值。

介绍

项目中使用了Angular 6框架,同时页面式样使用的是官方出的material。

<table mat-table [dataSource]="tableDataSource">
  <ng-container matColumnDef="select">
    <th mat-header-cell *matHeaderCellDef>
      <mat-checkbox (change)="$event ? masterToggle() : null" [checked]="tableSelection.hasValue() && isAllSelected()"
                    [indeterminate]="tableSelection.hasValue() && !isAllSelected()">

      </mat-checkbox>
    </th>
    <td mat-cell *matCellDef="let row">
      <mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? tableSelection.toggle(row) : null"
                    [checked]="tableSelection.isSelected(row)">

      </mat-checkbox>
    </td>
  </ng-container>
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef> 序号 </th>
    <td mat-cell *matCellDef="let element; index as i"> {{ i + 1}} </td>
  </ng-container>
  <ng-container matColumnDef="code">
    <th mat-header-cell *matHeaderCellDef> 产品编号 </th>
    <td mat-cell *matCellDef="let element"> {{element.code}} </td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> 产品名称 </th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>
  <ng-container matColumnDef="level">
    <th mat-header-cell *matHeaderCellDef> 产品层级 </th>
    <td mat-cell *matCellDef="let element"> {{element.level | level}} </td>
  </ng-container>
  <ng-container matColumnDef="state">
    <th mat-header-cell *matHeaderCellDef> 产品状态 </th>
    <td mat-cell *matCellDef="let element">{{element.state | enable}}</td>
  </ng-container>
  <ng-container matColumnDef="createdBy">
    <th mat-header-cell *matHeaderCellDef> 创建人 </th>
    <td mat-cell *matCellDef="let element"> {{showName(element.createdBy)}} </td>
  </ng-container>
  <ng-container matColumnDef="createdDate">
    <th mat-header-cell *matHeaderCellDef> 创建时间 </th>
    <td mat-cell *matCellDef="let element"> {{element.createdDate | date: 'yyyy-MM-dd HH:mm:ss'}} </td>
  </ng-container>
  <ng-container matColumnDef="lastModifiedBy">
    <th mat-header-cell *matHeaderCellDef> 修改人 </th>
    <td mat-cell *matCellDef="let element"> {{showName(element.lastModifiedBy)}} </td>
  </ng-container>
  <ng-container matColumnDef="lastModifiedDate">
    <th mat-header-cell *matHeaderCellDef> 修改时间 </th>
    <td mat-cell *matCellDef="let element"> {{element.lastModifiedDate | date: 'yyyy-MM-dd HH:mm:ss'}}
    </td>
  </ng-container>
  <ng-container matColumnDef="operate">
    <th mat-header-cell *matHeaderCellDef> 操作 </th>
    <td mat-cell *matCellDef="let element">
      <a mat-icon-button color="primary" title="编辑" [routerLink]="['/pages/product/', element.id]">
        <mat-icon>mode_edit</mat-icon>
      </a>
      <a *ngIf="element.state == 0" mat-icon-button color="primary" title="启用" (click)="changeState(element, 1);">
        <mat-icon>play_arrow</mat-icon>
      </a>
      <a *ngIf="element.state == 1" mat-icon-button color="primary" title="禁用" (click)="changeState(element, 0)">
        <mat-icon>pause</mat-icon>
      </a>
      <a mat-icon-button color="accent" (click)="remove(element.id)"  title="删除">
        <mat-icon>delete</mat-icon>
      </a>
    </td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

1. 列宽设置

如代码所示,最后一列为 matColumnDef="operate",在代码渲染时,会在该列添加 mat-column-operatecdk-column-operate 两个样式,这两个样式的规则是固定的:mat-column-(cdk-column-)+列名, 因此就可以通过设置两个样式中的一个,就可以控制该列的显示效果。在本代码中,由于operate列为3个按钮,默认样式下,无法在一行显示,可以进行设置列宽,确保3个按钮显示在一行:

.mat-column-operate {
    width125px;  // 每个按钮的width=40px,所以列宽比按钮总和略宽即可
}

2. 固定表头

<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>

在代码中有表头的设置。其中displayedColumns用于设置哪些列需要渲染出来,内容为string数组,且数据必须为上面代码中定义过的列名。sticky: true则是用来设置表头固定的,即较多数据时,显示竖向滚动条,滑动滚动条时,列表位置不变。需要注意的是,要想sticky设置起作用,需要对table的parent容器设置大小。
例子:

.table-container {
  overflow: auto;
  max-heightcalc(100vh - 270px);   // 通过css3的calc函数,设置自适应
}

3. 官方部分代码解析

在官方的例子中,有一部分代码写的很飘逸,充分发挥了函数式编程的优势。

下面进行代码解析

merge(this.sort.sortChange, this.paginator.page)  // 通过merge操作,将两个对象组装到一个操作过程中,两个对象,任意一个变更都会被监听到
  .pipe(
    startWith({}), // 设置默认值
    switchMap(() => {
      this.isLoadingResults = true;  // 启动加载框
      return this.exampleDatabase!.getRepoIssues(
        this.sort.active, this.sort.direction, this.paginator.pageIndex); // return返回一个Observable对象
    }),
    map(data => {
      // Flip flag to show that loading has finished.
      this.isLoadingResults = false;
      this.isRateLimitReached = false;
      this.resultsLength = data.total_count;

      return data.items;  // return返回值,将会重新返回到流里面,参与后续的计算
    }),
    catchError(() => {
      this.isLoadingResults = false;
      // Catch if the GitHub API has reached its rate limit. Return empty data.
      this.isRateLimitReached = true;
      return observableOf([]);  // 捕获异常后,然后空的对象,保证数据流正常进行
    })
  ).subscribe(data => this.data = data);  // 这里的data对应着 上一个return data.items


以上是关于Angular系列之MatTable小技巧的主要内容,如果未能解决你的问题,请参考以下文章

1000 行中的 Angular 6 MatTable 性能

Android课程---Android Studio使用小技巧:提取方法代码片段

VS中添加自定义代码片段——偷懒小技巧

提效小技巧——记录那些不常用的代码片段

linux命令使用小技巧系列之切换用户为什么加-

linux命令使用小技巧系列之切换用户为什么加-