1. 程式人生 > >基於 Angular Material 的 Data Grid 設計實現

基於 Angular Material 的 Data Grid 設計實現

![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200627174611906-1272921735.jpg) > 自 Extensions 元件庫釋出以來,Data Grid 成為了使用及諮詢最多的元件。最開始 Data Grid 的設計非常簡陋,經過一番重構,元件質量有了質的提升。 > Extensions 元件庫: [https://github.com/ng-matero/extensions](https://github.com/ng-matero/extensions) > Data Grid 示例: [https://ng-matero.github.io/extensions/data-grid](https://ng-matero.github.io/extensions/data-grid) 距離 Data Gird 重構已經過去了兩個多月,因工作忙碌而遲遲沒有介紹 Data Grid 的細節。這幾天又重構了一下官網示例,目前的 API 文件放在了 [gitbook](https://app.gitbook.com/@nzbin/s/material-extensions/) 上,暫時還沒有和官網整合,國內訪問會比較慢。本文會介紹 Data Grid 的使用方法及比較好的一些功能實現。說點題外話,**開發一款外掛最大的難度不在於功能的實現,而在於如何去設計外掛**。 ## 什麼是 Data Grid? Data Grid 本質上就是通過 `資料`+`列定義`+`配置項` 來渲染表格的外掛。這比寫一堆 DOM 結構要簡潔很多,可以說是 CRUD 業務中的大殺器之一。目前市面上功能最全的 Data Grid 是 [ag-grid](https://www.ag-grid.com/),很多元件庫也有自己的 Data Grid 實現,比如 [Ignite UI](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/grid.html),[Kendo UI](https://www.telerik.com/kendo-angular-ui/components/grid/)。但是市面上這些優秀的外掛基本都要收費,另外就是遇到變態需求時,第三方外掛的功能定製會遇到很多問題,這也是我自研 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(各種模板) 因文章篇幅有限,本文主要介紹一些重點功能,其它功能可以參考官網示例。 ### 基本用法 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626102718615-789150374.jpg) > 官網示例:[Basic](https://ng-matero.github.io/extensions/data-grid#basic) 定義元件引數 ```html
``` 定義資料及列 ```ts 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 ```js 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 ```html
``` 權衡各種利弊,Extensions Data Grid 選擇了第一種定義方法,介面定義如下: ```ts 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 | null; showExpand?: boolean; description?: string; i18n?: string; summary?: ((colData: any, colDef?: any) => void) | string; } ``` ### 模板 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626111959247-1923183564.jpg) 模板是 angular 元件極其靈活的一個功能。大部分優秀的第三方元件都具有自定義模板的能力,而在 Data Grid 中,模板更是一個不可或缺的功能。Extensions Data Grid 的模板功能已經比較完善,單元格模板除了基本的方法外,還增加了更為簡單易用的方法。 #### 普通方法 ```html Slide me! ``` ```ts export class AppComponent implements OnInit { @ViewChild('statusTpl', { static: true }) statusTpl: TemplateRef; 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](https://ng-matero.github.io/extensions/data-grid#custom-cell-template) 引用模板例項是一種很常見的思路,但是弊端就是必須將列定義寫在 ngOnInit 中,而且要先引用所用的自定義模板例項。這種寫法很不靈活。 #### 升級方案 ```html ``` > 官網示例:[Custom cell template 2](https://ng-matero.github.io/extensions/data-grid#custom-cell-template-2) 這種方法直接在元件引數中定義了模板例項,不需要再寫其它任何程式碼,非常簡單! 除了單元格模板之外,還有 headerTemplate、summaryTemplate、toolbarTemplate 等,可以滿足大部分的個性化需求,詳情見官網示例。 ### 選取 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626103339835-1123168463.jpg) > 官網示例:[Row selectable](https://ng-matero.github.io/extensions/data-grid#row-selectable) 表格的行選取是一個很常見的需求,用途廣泛。預設開啟單元格選取,可以設定 `[cellSelectable]="false"` 以關閉單元格選取。 通過 `[rowSelectable]="true"` 可以開啟行選取。 ```html ``` 通過 `[multiSelectable]="true"` 可以設定多選行。這裡有一個細節,按住 ctrl 並單擊才可以多選,或者直接點選 checkbox 也可以。如果需要隱藏 checkbox,只需要設定 `[hideRowSelectionCheckbox]="true"`。 如果初始化表格時希望預設選中某些行,則只需要定義 `[rowSelected]=[...]`。 #### 不可選取 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626110254209-1846383215.jpg) 設定不可選取行的方式有兩種,一種是設定 checkbox 為 disabled,另一種是隱藏 checkbox。配置非常簡單,只需要通過 `rowSelectionFormatter` 過濾資料即可。 ```html ``` ```ts 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', }; } ``` ### 行展開 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626103402308-1197363292.jpg) > 官網示例:[Expandable row](https://ng-matero.github.io/extensions/data-grid#expandable-row) 行展開的實現藉助了 Angular Material 表格的 `multiTemplateDataRows` 引數,實現細節很多。Data Grid 的程式碼如下: 設定 `expandable` 和 `expansionTemplate` ```html {{row.name}} ``` 在列定義中設定 `showExpand`, 確定在哪個列顯示展開符號。 ```ts 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; } ``` ### 列操作 ![](https://img2020.cnblogs.com/blog/999445/202006/999445-20200626110405972-517823155.jpg) > 官網示例:[Column hiding & moving](https://ng-matero.github.io/extensions/data-grid#column-hiding-moving) 列的顯示隱藏以及排序是非常常見的需求,這類需求曾被產品經理折磨了無數次。目前的列操作 UI 只有選單方式,之後還會新增側邊欄的 UI,暫時不支援列的橫向拖拽。 列的操作完全可以移到元件之外,通過設定 columns 實現,並不一定非要用 Data Grid 整合好的功能。 ## 總結 因篇幅有限,很多 Data Grid 的功能沒有詳細介紹。從我遇到的需求來看,目前的 Data Grid 已經可以覆蓋九成的需求了,還有很多高階功能正在開發當中,歡迎大家提出建設性意見。如果大家在使用元件的過程中遇到問題,可以在 GitHub 中提交 [issues](https://github.com/ng-matero/extensions/issues) 或者進討論群提問。