基于 Angular Material 的 Data Grid 设计实现

自 Extensions 组件库发布以来,Data Grid 成为了使用及咨询最多的组件。最开始 Data Grid 的设计非常简陋,经过一番重构,组件质量有了质的提升。
Extensions 组件库: https://github.com/ng-matero/extensions
Data Grid 示例: https://ng-matero.github.io/extensions/data-grid
距离 Data Gird 重构已经过去了两个多月,因工作忙碌而迟迟没有介绍 Data Grid 的细节。这几天又重构了一下官网示例,目前的 API 文档放在了 gitbook 上,暂时还没有和官网整合,国内访问会比较慢。本文会介绍 Data Grid 的使用方法及比较好的一些功能实现。说点题外话,开发一款插件最大的难度不在于功能的实现,而在于如何去设计插件。
什么是 Data Grid?
Data Grid 本质上就是通过 数据+列定义+配置项 来渲染表格的插件。这比写一堆 DOM 结构要简洁很多,可以说是 CRUD 业务中的大杀器之一。目前市面上功能最全的 Data Grid 是 ag-grid,很多组件库也有自己的 Data Grid 实现,比如 Ignite UI,Kendo UI。但是市面上这些优秀的插件基本都要收费,另外就是遇到变态需求时,第三方插件的定制性比较困难,这也是我自研 Data Grid 的初衷。
Angular Material 对于 table 的封装已经足够灵活,但是模板的定义依然很繁琐,也缺少很多刚需功能。Data Grid 几乎整合了 Angular Material 表格的所有功能,同时又增加了很多实用功能。
Extensions Data Grid 简介
Extensions Data Grid 的功能实现参考了 ag-grid 以及其它插件,重构时对变量及参数命名进行了很细致的考究。目前 Data Grid 已经实现的功能如下:
- paging(分页,包括前端分页和后端分页)
- sorting(排序,目前只支持单一排序)
- sticky columns(列的固定)
- column hiding(列的显示隐藏)
- checkbox selection(数据选择)
- row selection(行选取,可多选)
- cell selection(单元格选取,暂时支持单选)
- expandable row(可展开的表格行)
- customized cell(自定义单元格)
- column moving(列的移动排序)
- Data Formatting(数据格式化)
- Template(各种模板)
因文章篇幅有限,本文主要介绍一些重点功能,其它功能可以参考官网示例。
基本用法

官网示例:Basic
定义组件参数
<mtx-grid [data]="list"
[columns]="columns">
</mtx-grid>
定义数据及列
export class AppComponent {
columns: MtxGridColumn[] = [
{ header: 'Name', field: 'name' },
{ header: 'Weight', field: 'weight' },
{ header: 'Gender', field: 'gender' },
{ header: 'Mobile', field: 'mobile' },
{ header: 'City', field: 'city' },
];
list = EXAMPLE_DATA;
}
补充介绍一下,市面上 Data Grid 定义列的方式主要有两种:
1、JS 定义,比如 ag-grid
var gridOptions = {
// define 3 columns
columnDefs: [
{ headerName: 'Athlete', field: 'athlete' },
{ headerName: 'Sport', field: 'sport' },
{ headerName: 'Age', field: 'age' }
],
// other grid options here...
}
2、模板定义,比如 Ignite UI
<igx-grid igxPreventDocumentScroll #grid1 [data]="data | async" [height]="'500px'" width="100%" [autoGenerate]='false' [allowFiltering]="true">
<igx-column [field]="'Category'" [width]="'120px'"></igx-column>
<igx-column [field]="'Type'" [width]="'150px'" [filterable]='false'></igx-column>
<igx-column [field]="'Open Price'" [width]="'120px'" dataType="number" [formatter]="formatCurrency">
</igx-column>
<igx-column [field]="'Price'" [width]="'120px'" dataType="number" [formatter]="formatCurrency"></igx-column>
</igx-grid>
权衡各种利弊,Extensions Data Grid 选择了第一种定义方法,接口定义如下:
export interface MtxGridColumn {
field: string;
header?: string;
hide?: boolean;
disabled?: boolean;
pinned?: 'left' | 'right';
left?: string;
right?: string;
width?: string;
resizable?: boolean;
sortable?: boolean | string;
type?: 'tag' | 'button' | 'link' | 'image' | 'number' | 'currency' | 'percent' | 'boolean';
tag?: MtxGridColumnTag;
buttons?: MtxGridColumnButton[];
formatter?: (rowData: any, colDef?: any) => void;
cellTemplate?: TemplateRef<any> | null;
showExpand?: boolean;
description?: string;
i18n?: string;
summary?: ((colData: any, colDef?: any) => void) | string;
}
模板

模板是 angular 组件极其灵活的一个功能。大部分优秀的第三方组件都具有自定义模板的能力,而在 Data Grid 中,模板更是一个不可或缺的功能。Extensions Data Grid 的模板功能已经比较完善,单元格模板除了基本的方法外,还增加了更为简单易用的方法。
普通方法
<mtx-grid [data]="list"
[columns]="columns">
</mtx-grid>
<ng-template #statusTpl let-row let-index="index" let-col="colDef">
<mat-slide-toggle [checked]="row.status">Slide me!</mat-slide-toggle>
</ng-template>
export class AppComponent implements OnInit {
@ViewChild('statusTpl', { static: true }) statusTpl: TemplateRef<any>;
columns: MtxGridColumn[] = [];
list = EXAMPLE_DATA;
ngOnInit() {
this.columns = [
{ header: 'Name', field: 'name' },
{ header: 'Weight', field: 'weight' },
{ header: 'Gender', field: 'gender' },
{ header: 'Mobile', field: 'mobile' },
{ header: 'City', field: 'city' },
{ header: 'Status', field: 'status', cellTemplate: this.statusTpl },
];
}
}
官网示例:Custom cell template
引用模板实例是一种很常见的思路,但是弊端就是必须将列定义写在 ngOnInit 中,而且要先引用所用的自定义模板实例。这种写法很不灵活。
升级方案
<mtx-grid [data]="list"
[columns]="columns"
[cellTemplate]="{ city: cityTpl }">
</mtx-grid>
<ng-template #cityTpl let-row let-index="index" let-col="colDef">
<button mat-raised-button color="primary">{{row.city}}</button>
</ng-template>
这种方法直接在组件参数中定义了模板实例,不需要再写其它任何代码,非常简单!
除了单元格模板之外,还有 headerTemplate、summaryTemplate、toolbarTemplate 等,可以满足大部分的个性化需求,详情见官网示例。
选取

官网示例:Row selectable
表格的行选取是一个很常见的需求,用途广泛。默认开启单元格选取,可以设置 [cellSelectable]="false" 以关闭单元格选取。
通过 [rowSelectable]="true" 可以开启行选取。
<mtx-grid [data]="list"
[columns]="columns"
[rowSelectable]="rowSelectable"
(rowSelectionChange)="log($event)"
(cellSelectionChange)="log($event)">
</mtx-grid>
通过 [multiSelectable]="true" 可以设置多选行。这里有一个细节,按住 ctrl 并单击才可以多选,或者直接点击 checkbox 也可以。如果需要隐藏 checkbox,只需要设置 [hideRowSelectionCheckbox]="true"。
如果初始化表格时希望默认选中某些行,则只需要定义 [rowSelected]=[...]。
不可选取

设置不可选取行的方式有两种,一种是设置 checkbox 为 disabled,另一种是隐藏 checkbox。配置非常简单,只需要通过 rowSelectionFormatter 过滤数据即可。
<mtx-grid [data]="list"
[columns]="columns"
[rowSelectable]="true"
[rowSelectionFormatter]="rowSelectionFormatter">
</mtx-grid>
export class AppComponent {
columns: MtxGridColumn[] = [
{ header: 'Name', field: 'name' },
{ header: 'Weight', field: 'weight' },
{ header: 'Gender', field: 'gender' },
{ header: 'Mobile', field: 'mobile' },
{ header: 'City', field: 'city' },
];
list = EXAMPLE_DATA;
rowSelectionFormatter: MtxGridRowSelectionFormatter = {
disabled: (data) => data.name === 'Boron',
hideCheckbox: (data) => data.name === 'Helium',
};
}
行展开

官网示例:Expandable row
行展开的实现借助了 Angular Material 表格的 multiTemplateDataRows 参数,实现细节很多。Data Grid 的代码如下:
设置 expandable 和 expansionTemplate
<mtx-grid [data]="list"
[columns]="columns"
[expandable]="true"
[expansionTemplate]="expansionTpl">
</mtx-grid>
<ng-template #expansionTpl let-row>
{{row.name}}
</ng-template>
在列定义中设置 showExpand, 确定在哪个列显示展开符号。
export class AppComponent {
columns: MtxGridColumn[] = [
{ header: 'Name', field: 'name', showExpand: true },
{ header: 'Weight', field: 'weight' },
{ header: 'Gender', field: 'gender' },
{ header: 'Mobile', field: 'mobile' },
{ header: 'City', field: 'city' },
];
list = EXAMPLE_DATA;
}
列操作

列的显示隐藏以及排序是非常常见的需求,这类需求曾被产品经理折磨了无数次。目前的列操作 UI 只有菜单方式,之后还会添加侧边栏的 UI,暂时不支持列的横向拖拽。
列的操作完全可以移到组件之外,通过设置 columns 实现,并不一定非要用 Data Grid 集成好的功能。
总结
因篇幅有限,很多 Data Grid 的功能没有详细介绍。从我遇到的需求来看,目前的 Data Grid 已经可以覆盖九成的需求了,还有很多高级功能正在开发当中,欢迎大家提出建设性意见。如果大家在使用组件的过程中遇到问题,可以在 GitHub 中提交 issues 或者进讨论群提问。
基于 Angular Material 的 Data Grid 设计实现的更多相关文章
- Ng-Matero:基于 Angular Material 搭建的中后台管理框架
前言 目前市面上关于 Angular Material 的后台框架比较少,大多都是收费主题,而且都不太好用. 很多人都说 Material 是一个面向 C 端的框架,其实在使用其它框架做管理系统的时候 ...
- Angular Material 的设计之美
前言 Angular Material 作为 Angular 的官方组件库,无论是设计交互还是易用性都有着极高的质量.正如官方所说其目的就是构建基于 Angular 和 Typescript 的高质量 ...
- Angular Material
Angular Material 的设计之美 Ng-Matero 0.3 已发布,新增 module schematic 以及 page schematic,详见 README 前言 Angula ...
- Angular Material design设计
官网: https://material.io/design/ https://meterial.io/components 优秀的Meterial design站点: http://material ...
- 项目演化系列--验证体系(基于angular的前端验证)
前言 之前分享的<web项目演化--验证体系>中提到基于angular的验证,但是为了以防读者迷惑,能够好的理解验证体系,所以没有详细介绍. 今天特地补写一篇关于构建angular的验证. ...
- [转]VS Code 扩展 Angular 6 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout
本文转自:https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode VSCode Angular Typ ...
- Angular Material & Hello World
前言 Angular Material(下称Material)的组件样式至少是可以满足一般的个人开发需求(我真是毫无设计天赋),也是Angular官方推荐的组件.我们通过用这个UI库来快速实现自己的i ...
- 手势模型和Angular Material的实现
iPhone的出现让手势操作大为流行,也使得手势编程成为开发人员的挑战. 拟物设计也把手势编程纳入在内,大概也想制定一个在交互模型标准.现阶段因为MD还在预发布阶段,因此还只实现了单点手势(一个指头) ...
- 基于Verilog HDL 的数字时钟设计
基于Verilog HDL的数字时钟设计 一.实验内容: 利用FPGA实现数字时钟设计,附带秒表功能及时间设置功能.时间设置由开关S1和S2控制,分别是增和减.开关S3是模式选择:0是正常时钟 ...
随机推荐
- 核心记账业务可用jdk7的PriorityBlockingQueue优先阻塞队列结合乐观锁实现
-- 1.优先级阻塞队列 当前核心记账业务是悲观锁实现,但考虑到高并发和死锁的问题,可以用PriorityBlockingQueue优先阻塞队列结合乐观锁实现,对于并发时出现锁无法update时可以重 ...
- Qcom rampdump解析工具使用
使用如下命令获取qcom工具: ljj@ljj-ThinkCentre-M83:~/git/qcom_tools/ramdump$ git clone git://codeaurora.org/qui ...
- Java实现 蓝桥杯 算法提高 分解质因数(暴力)
试题 算法提高 分解质因数 问题描述 给定一个正整数n,尝试对其分解质因数 输入格式 仅一行,一个正整数,表示待分解的质因数 输出格式 仅一行,从小到大依次输出其质因数,相邻的数用空格隔开 样例输入 ...
- Java实现蓝桥杯3n+1问题
3n+1 [问题描述] 考虑如下的序列生成算法:从整数 n 开始,如果 n 是偶数,把它除以 2:如果 n 是奇数,把它乘 3 加1.用新得到的值重复上述步骤,直到 n = 1 时停止.例如,n = ...
- Java实现 蓝桥杯VIP 算法提高 最小乘积(提高型)
算法提高 最小乘积(提高型) 时间限制:1.0s 内存限制:512.0MB 问题描述 给两组数,各n个. 请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小.要求程序输出这个最 ...
- Java实现 蓝桥杯VIP 算法提高 洗牌
算法提高 洗牌 时间限制:1.0s 内存限制:256.0MB 问题描述 小弱T在闲暇的时候会和室友打扑克,输的人就要负责洗牌.虽然小弱T不怎么会洗牌,但是他却总是输. 渐渐地小弱T发现了一个规律:只要 ...
- java实现第三届蓝桥杯DNA对比
DNA对比 脱氧核糖核酸即常说的DNA,是一类带有遗传信息的生物大分子.它由4种主要的脱氧核苷酸(dAMP.dGMP.dCMT和dTMP)通过磷酸二酯键连接而成.这4种核苷酸可以分别记为:A.G.C. ...
- Java实现第九届蓝桥杯阶乘位数
阶乘位数 题目描述 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞&qu ...
- java实现第七届蓝桥杯七星填数
七星填数 如图[图1.png]所示. 在七角星的14个节点上填入1~14 的数字,不重复,不遗漏. 要求每条直线上的四个数字之和必须相等. 图中已经给出了3个数字. 请计算其它位置要填充的数字,答案唯 ...
- Python爬虫之request +re
什么是爬虫? 它是指向网站发起请求,获取资源后分析并提取有用数据的程序: 爬虫的步骤: 1.发起请求 使用http库向目标站点发起请求,即发送一个Request Request包含:请求头.请求体等 ...