refer :

https://material.angular.io/cdk/table/overview

https://material.angular.io/components/table/overview

通常我们做 control panel 时会大量运用到 table

尤其是处理 CRUD 时, table 更是神器

说到 table 就一定会附带以下这些东西

filter, search

pagination

sort

show/hide/sort columns

select row

cell display

Table 作为高复用组件, 必须要足够抽象。

material 在这里也是一如往常的做出了数据和 ui 分离.

这个概念和 angular directive form 是一样的.

数据方面的处理是交给 DataSource 这个对象来负责.

这个对象监听 filter, search, sort 等等数据的变动,然后对数据进行处理 (mat table data source 目前没有支持远程数据处理, 我们得自己实现)

然后 ui table 通过监听 data source 来获取新数据.

各种小组件, mat-sort, mat-pagination 则是负责监听 ui 操作.

所以是

data source 监听操作小组件 -> 更新 source

ui table 监听 data source -> 渲染

这个就是大致上架构的设计啦,我们只能跟着做了

下面说说常用的东西.

1. ui table

首先开一个"家“ 监听 data source

<table mat-table [dataSource]="dataSource" [trackBy]="trackByFn" >
</table>

然后是里面

<ng-container matColumnDef="cost">
<th mat-header-cell *matHeaderCellDef> Cost </th>
<td mat-cell *matCellDef="let data"> {{data.cost}} </td>
<td mat-footer-cell *matFooterCellDef> {{totalCost}} </td>
</ng-container> ... <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let myRowData; columns: columnsToDisplay"></tr>
<tr mat-footer-row *matFooterRowDef="columnsToDisplay"></tr>

定义每一个 column template

一个 column 又分为 3 个 template 展现,  header,body,footer

最后 3 行则是定义 row 的呈现.

不是每一个 column 都有 3 个展现的, 有些只有 header, body, 有些则只有 footer, 没有就不要定义就好了

row 的 columnsToDisplay 也不是全部一样的, 有一些 columns 只需要展现在 footer, 那么它就只出现在 row footer 的 columnsToDisplay 就好了。

2. max-text-column, 这个就是一个方便啦. 因为大部分都是 display string 嘛.

<mat-text-column name="score"></mat-text-column>

源码是很简单的

@Component({
moduleId: module.id,
selector: 'mat-text-column',
template: `
<ng-container matColumnDef>
<th mat-header-cell *matHeaderCellDef [style.text-align]="justify">
{{headerText}}
</th>
<td mat-cell *matCellDef="let data" [style.text-align]="justify">
{{dataAccessor(data, name)}}
</td>
</ng-container>
`,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.Default,
})
export class MatTextColumn<T> extends CdkTextColumn<T> {
}

通过 CdkTextColumn @input 去修改 header or cell,

@Input() headerText: string;
@Input() dataAccessor: (data: T, name: string) => string;

3. Paginator

这个就是上面说的操作小组件啦,

  <mat-paginator #matPaginator [pageSizeOptions]="[1, 10, 20]"></mat-paginator>

通过 #matPaginator 打标签, 然后 controller 就可以用 ViewChild 找到它

@ViewChild('matPaginator', { read: MatPaginator, static: false })
matPaginator: MatPaginator;

这里我用 static false,大部分情况 true 是 ok 的, 不熟悉的人可以看看 angular 8.0 了解一下.

ngAfterViewInit() {
this.dataSource.paginator = this.matPaginator;
}

然后就是让它与 data source 关联, 这样 data source 就会监听这个小组件了. 每一次 ui 换 page, data source 就能过去换数据了.

注意: dataSource.paginator 是一个 getter setter 属性来的, 所以即使我们在 AfterViewInit 才 set, ui table 一样会渲染.

源码 :

  get paginator(): MatPaginator | null { return this._paginator; }
set paginator(paginator: MatPaginator|null) {
this._paginator = paginator;
this._updateChangeSubscription(); // ui table 监听到这个就会 render 了咯
}
private _paginator: MatPaginator|null;

4. Sort

和上面沟通差不多, 在 table 打上 matSort 指令和 #matSort, 这里要对准 matSort 的 exportAs 哦

题外话标签对上指令就要对准 exportAs, 标签 defualt 是拿 element 和 component 的

  <table mat-table [dataSource]="dataSource" [trackBy]="trackByFn" matSort #matSort="matSort" >

然后我们在我们想 sort 的 header 加上 mat-sort-header 指令

<ng-container matColumnDef="Id">
<th mat-header-cell *matHeaderCellDef mat-sort-header >Id</th>
<td mat-cell *matCellDef="let row"> {{row.Id}} </td>
</ng-container>

不是每一个 column 都是可以 sort 的嘛, 当然需要表态一下咯,

看出来, matSort 基本上只是为了沟通而诞生的.

@ViewChild('matSort', { read: MatSort, static: false })
matSort: MatSort; ngAfterViewInit() {
this.dataSource.paginator = this.matPaginator;
this.dataSource.sort = this.matSort;
}

5. filter search

这个我就不多说了,

this.dataSource.filter = 'string here';

它也是 setter 所以每次值改变了它都会跑

自定义 data source

上面说了 material data source 只能处理 local 数据. 但是真实项目里我们的数据大部分是 backend 来的,要通过 api 去拿才行.

我自己使用了 odata 所以对于做 dynamic table 来说还是比较轻松的.

我们沿着 material 的思路走, 一样使用 material 提供的操作小组件 sort, paginator 只是自己实现 data source 就好.

所以这里我们主要看看怎样让它们沟通.

Paginator

this.matPaginator.length = 1000;
this.matPaginator.pageIndex = 0; // 注意 0 是开始, 而不是 1
this.matPaginator.page.subscribe((e: PageEvent) => {
// pageIndex 或 pageSize 变化时触发
console.log(e.length);
console.log(e.pageIndex);
console.log(e.pageSize);
console.log(e.previousPageIndex);
});

当 data source 获取到资料后, 就可以 set length 了 (这个 length 是说数据库里有多少, 而不是拿下来了多少哦)

如果是 filter update 了, 通常 pageIndex 都会 set to start, 所以这个接口会用到.

当我们 set pageIndex 和 length 时, 是不会触发 PageEvent 事件的哦。它会去同步 view 而已.

最后就是监听用户的操作了.

说说目前 material 的缺失.

1. loading and data not found

这么基本的功能都没有....

https://github.com/angular/components/issues/8661

workaround : 放 loading 和 not found 放到 table 下面. 没有 footer 的情况下, 看不出来. 有 footer 自己保重

2. column resize

https://github.com/angular/components/issues/8312

这个也是很基本的功能,也是没有,

work aound: 自己可以勉强实现啦... 不过...

3. drag and drop row

这个也是基本功能, 自己实现也是很累的...

https://github.com/angular/components/issues/13770

4. visual scroll

这个不只是 table, 所有 material 能用到 visual scroll 的大部分都没有 build in 的实现

甚至说,很难去实现...

https://github.com/angular/components/issues/10122

最后吐槽一下, 不只是 material, angular 还有很多很多的功能都不齐全.

只有用的人才知道它的局限有多大. 当然我的意思不是说其它框架有实现.

只是作为一个大而全的框架,我对待它的要求就是.... 我只想写业务逻辑相关的代码..... 哈哈哈

预计 angular 10 或 11 之后就会很不错了.

Angular Material (Components Cdk) 学习笔记 Table的更多相关文章

  1. 关于Angular.js Routing 的学习笔记(实现单页应用)

    最近开始学习angular.js,发现angular.js确实很方便,也很强大.在看到 AngularJS Routing and Multiple Views 这一部分的时候,有点乱.现在通过记录一 ...

  2. Angular.js之指令学习笔记

    <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"& ...

  3. Angular.js之Router学习笔记

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  4. html学习笔记 - table表格

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 重磅教程!帮你全面彻底搞定Material design的学习笔记

    http://www.uisdc.com/comprehensive-material-design-note

  6. Angular 2 to Angular 4 with Angular Material UI Components

    Download Source - 955.2 KB Content Part 1: Angular2 Setup in Visual Studio 2017, Basic CRUD applicat ...

  7. Angular Material design设计

    官网: https://material.io/design/ https://meterial.io/components 优秀的Meterial design站点: http://material ...

  8. dot language 学习笔记

    dot language 学习笔记 UP | HOME   dot language 学习笔记 Table of Contents 1 dot 语言简介 2 基本语法 2.1 常用图形 2.2 常用线 ...

  9. Angular 学习笔记 ( CDK - Accessibility )

    @angular/ckd 是 ng 对于 ui 组建的基础架构. 是由 material 团队开发与维护的, 之所以会有 cdk 看样子是因为在开发 material 的时候随便抽象一个层次出来给大家 ...

随机推荐

  1. MQ消息机制如何确认消费了消息?

    消息队列如何保证消息能百分百成功被消费 目前常用的消息队列有很多种,如RabbitMQ,ActiveMQ,Kafka...下面以RabbitMQ为例来讲如何保证消息队列中的信息能百分百被消费掉. 其中 ...

  2. nginx listen 端口 443 80 https 和 wss

    端口号 443 和 80 端口的区别 一般指定 443 和 80 端口都是使用域名时所需要的 当我们使用域名请求时,一般是不添加端口号的 例如:http://www.baidu.com 在不添加端口号 ...

  3. 创建WebApi Odata v3 终结点

    开放数据协议(OData) 是用于 web 的数据访问协议. OData 提供统一的方法来构造数据. 查询的数据和操作该数据集通过 CRUD 操作 (创建. 读取. 更新和删除). OData 支持 ...

  4. typeScript模块<四>

    /* 功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb 要求1:Mysql MsSql MongoDb功能一样 都有 add update delete get方法 注意:约 ...

  5. python-learning-第二季-画图matplotlib

    https://www.bjsxt.com/down/8468.html 绘制方法: 绘制直线: #coding:utf- import matplotlib.pyplot as plt #准备绘制的 ...

  6. Access与SQL中的IsNull(),IS NULL的区别

    Access也有IsNull函数,但意义和参数却和T-SQL中的不同. 在T-SQL(也就是SQL Server所支持的SQL语言)中,IsNull的作用是把空值替代成指定的值.然而在Access中, ...

  7. Spring cloud微服务安全实战-3-11API安全机制之登录

    流控.认证.审计.授权以上都做了初步的简单的实现. 之前写的代码,base64加密了用户名和密码. 缺点1:每次请求都要带用户名密码 增加了泄露的风险. 每次传上来用户名和密码都要check验证.ch ...

  8. delphi十六进制字符串hex转byte数组互相转换bmp图片

    procedure Hex2Png(str: string; out png: TPngObject); var stream: TMemoryStream; begin if not Assigne ...

  9. 【计算机视觉】OpenCV篇(6) - 平滑图像(卷积/滤波/模糊/降噪)

    平滑滤波 平滑滤波是低频增强的空间域滤波技术.空间域滤波技术即不经由傅立叶转换,直接处理影像中的像素,它的目的有两类:一类是模糊:另一类是消除噪音.空间域的平滑滤波一般采用简单平均法进行,就是求邻近像 ...

  10. log4net使用简明教程,快看看哟

    在项目当中经常会遇到各种各样的问题,如何可以尽快找到问题,那么就只能靠日志了,所以一个系统的日志是否完备合理就尤为重要. 在日志管理插件中log4net相当流行,下面就简单说明一下使用方法. log4 ...