###### tags: `Angular` `ag-Grid` # 🌝[T]ag-Grid Drill down ## 需求簡述 SD希望可以在grid上加上`Drill down`的功能(點擊資料,可以展開/收起詳細資料)。 ## 資料蒐集 ### Kendo 網路上找到的套件`Kendo`,看起來有支援Angular做Detail功能的套件,且有兩種樣板可以選擇。 #### [Detail Row Template](https://www.telerik.com/kendo-angular-ui/components/grid/master-detail/detail-template/) ![](https://i.imgur.com/OwICEeg.png) #### [Master-Detail Grids](https://www.telerik.com/kendo-angular-ui/components/grid/master-detail/) ![](https://i.imgur.com/1tUhwt4.png) :::danger ❌現階段不希望多載入一個套件來做這件事,因此就沒有多研究此套件了。 ::: ### ag-Grid #### [Master/Detail](https://www.ag-grid.com/javascript-grid-master-detail/) A1目前是使用ag-Grid的套件來實現grid的功能,但ag-Grid提供相符SD需求的功能是需要付費的。 ![](https://i.imgur.com/5GomP8c.png) :::success ✔必須想辦法以不付費的方式來達到此效果。 ::: ## 實現筆記 > **agGrid** > * onCellClicked()。 > * [Full Width Rows](https://www.ag-grid.com/javascript-grid-full-width-rows/)。 > * HTML+CSS。 :::info 💡要使列(row)為全屏寬度(fullWidth)必須實現isFullWidthCell及提供fullWidthCellRenderer ::: ### isFullWidthCell 使用isFullWidthCell告知哪些列是為全屏寬度的。 > this.gridOptions.api.setRowData(data)後,每列都會跑一次isFullWidthCell。 ==balance-list.component.ts== ```typescript isFullWidthCell = function (rowNode) { return typeof (rowNode.data.detail) === 'string'; }; ``` ### fullWidthCellRenderer 提供一個fullWidthCellRenderer,讓grid cellRenderer在進行fullWidth渲染時要使用什麼。 ==balance-list.component.ts== ```typescript fullWidthCellRenderer = (params) => { let cssClass; // rowPinned 是凍結列的意思 if (params.node.rowPinned) { cssClass = 'example-full-width-pinned-row'; } else { cssClass = 'example-full-width-row'; } // Create new DOM element const eDiv = document.createElement('div'); eDiv.innerHTML = `<div class="${cssClass}">${params.data.detail}</div>`; return eDiv.firstChild; } ``` ### getRowHeight 設定row高度用,可依自己需求指定高度。 ==balance-list.component.ts== ```typescript getRowHeight = function (params) { if (!params) { return 30; } return params.data.detail ? params.data.count * 30 : 30; }; ``` ### onCellClicked 單點擊 ==a1-grid.component.ts== ```typescript this.gridOptions.onCellClicked = (event) => { this.onCellClicked.emit(event); }; ``` 偵測到點擊後,將資料整理成HTML樣式的字串,在這邊就要將詳細資料的畫面準備好。 > CSS世騏學長設計,HTML套世騏學長提供。 ==balance-list.component.ts== ```typescript onRowClicked(params) { // 詳細資料(Detail) /*準備資料 #依點擊Type & ReasonName為依據*/ const rowData: BalanceList = params.data; const rowDetail = this.balanceList.filter(item => item.Type == rowData.Type && item.ReasonName == rowData.ReasonName && !!item.BShortName); /*資料畫面 #detail:放HTML(畫面+資料) #count:依筆數給高度*/ const gridData = this.a1Grid.getAllGridData(); const gridDetail = { detail: '', count: 0}; /*資料畫面 #身體資料*/ rowDetail.forEach((detail, i) => { /*規格上的TenantAmount = TotalAmount*/ gridDetail.detail += `<tr> <td style="width: 100px;">${detail.BShortName}</td> <td style="width: 100px;">${detail.TenantQty}</td> <td style="width: 100px;">${this.decimalPipe.transform(detail.TotalAmount, '')}</td> </tr>`; gridDetail.count = i + 2; }); /*資料畫面 #標題名稱*/ gridDetail.detail = `<table> <tbody> <tr> <th style="width: 100px;">分店簡稱</th> <th style="width: 100px;">數量</th> <th style="width: 100px;">金額</th> </tr> ${gridDetail.detail} </tbody> </table>`; // 詳細資料收起|展開 /*收起*/ if (gridData[params.rowIndex + 1] && gridData[params.rowIndex + 1].detail) { gridData.splice(params.rowIndex + 1, 1); } else if (rowDetail.length > 0) { /*展開*/ gridData.splice(params.rowIndex + 1, 0, gridDetail); } this.a1Grid.setGridRowData(gridData); } ```