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-operate
和 cdk-column-operate
两个样式,这两个样式的规则是固定的:mat-column-(cdk-column-)+列名
, 因此就可以通过设置两个样式中的一个,就可以控制该列的显示效果。在本代码中,由于operate列为3个按钮,默认样式下,无法在一行显示,可以进行设置列宽,确保3个按钮显示在一行:
.mat-column-operate {
width: 125px; // 每个按钮的width=40px,所以列宽比按钮总和略宽即可
}
2. 固定表头
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
在代码中有表头的设置。其中displayedColumns
用于设置哪些列需要渲染出来,内容为string数组,且数据必须为上面代码中定义过的列名。sticky: true
则是用来设置表头固定的,即较多数据时,显示竖向滚动条,滑动滚动条时,列表位置不变。需要注意的是,要想sticky设置起作用,需要对table的parent容器设置大小。
例子:
.table-container {
overflow: auto;
max-height: calc(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 性能