自 Extensions 組件庫發佈以來,Data Grid 成爲了使用及諮詢最多的組件。最開始 Data Grid 的設計很是簡陋,通過一番重構,組件質量有了質的提高。
Extensions 組件庫: https://github.com/ng-matero/extensions
Data Grid 示例: https://ng-matero.github.io/extensions/data-grid
距離 Extensions Data Grid 重構已通過去了兩個多月,因工做忙碌而遲遲沒有介紹 Extensions Data Grid 的細節。這幾天又重構了一下官網示例,目前的 API 文檔放在了 gitbook 上,暫時尚未和官網整合,國內訪問會比較慢。本文會介紹 Data Grid 的使用方法及比較好的一些功能實現。說點題外話,開發一款插件最大的難度不在於功能的實現,而在於如何去設計插件。html
Data Grid 本質上就是經過 數據
+列定義
+配置項
來渲染表格的插件。這比寫一堆 DOM 結構要簡潔不少,能夠說是 CRUD 業務中的大殺器之一。目前市面上功能最全的 Data Grid 是 ag-grid,不少組件庫也有本身的 Data Grid 實現,好比 Ignite UI,Kendo UI。可是市面上這些優秀的插件基本都要收費,另外就是遇到變態需求時,第三方插件的功能定製會遇到不少問題,這也是我自研 Data Grid 的初衷。前端
Angular Material 對於 table 的封裝已經足夠靈活,可是模板的定義依然很繁瑣,也缺乏不少剛需功能。Extensions Data Grid 幾乎整合了 Angular Material 表格的全部功能,同時又增長了不少實用功能。git
Extensions Data Grid 的功能實現參考了 ag-grid 以及其它插件,重構時對變量及參數命名進行了很細緻的考究。目前 Extensions Data Grid 已經實現的功能以下:github
因文章篇幅有限,本文主要介紹一些重點功能,其它功能能夠參考官網示例。後端
官網示例: Basic
定義組件參數app
<mtx-grid [data]="list" [columns]="columns"> </mtx-grid>
定義數據及列async
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 定義列的方式主要有兩種:ide
一、JS 定義,好比 ag-gridui
var gridOptions = { // define 3 columns columnDefs: [ { headerName: 'Athlete', field: 'athlete' }, { headerName: 'Sport', field: 'sport' }, { headerName: 'Age', field: 'age' } ], // other grid options here... }
二、模板定義,好比 Ignite UIthis
<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>
官網示例: Custom cell template 2
這種方法直接在組件參數中定義了模板實例 [cellTemplate]="{ city: cityTpl }"
,其中 city
是列定義中的 field
,除此以外不須要再寫其它任何代碼,很是簡單!
除了單元格模板以外,還有 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; }
官網示例: Column hiding & moving
列的顯示隱藏以及排序是很是常見的需求,這類需求曾被產品經理折磨了無數次。目前的列操做 UI 只有菜單方式,以後還會添加側邊欄的 UI,暫時不支持列的橫向拖拽。
列的操做徹底能夠移到組件以外,經過設置 columns 實現,並不必定非要用 Data Grid 集成好的功能。
因篇幅有限,不少 Extensions Data Grid 的功能沒有詳細介紹。從我遇到的需求來看,目前的 Data Grid 已經能夠覆蓋九成的需求了,還有不少高級功能正在開發當中,歡迎你們提出建設性意見。若是你們在使用組件的過程當中遇到問題,能夠在 GitHub 中提交 issues 或者進討論羣提問。