本次情境
本次需求是要將同一個客戶的資料重新組合在一起,並將有相同的資料要跨欄在 table 呈現,不要問我為什麼後端不處理…就記錄一下這次專案上遇到的問題…
資料範例如下
1 | data=[ |
觀察相同點
以前兩筆資料為例,可以看到有 CFID
、ORDERFLAG
、USERNM
這三個欄位相同,CFID 看起來就是這筆資料的唯一代碼,所以我想說要從這裡下手。
groupby
首先在 util.service
建立一個 groupby 方法。
service 可自訂義,只是剛好專案把很多功能類的方法寫在此 service 內
util.service.ts
1 | groupBy<T>(array: Array<T>, key: any): any { |
使用 groupby 轉資料
1 | getData() { |
使用 groupby 方法重組資料,第一個參數要帶目前的資料陣列,第二個參數要帶以什麼為基準的 key。
console 出來會看到資料變成這樣
1 | 11111111:(2)[(...),(...)], |
然後到這邊我就卡住了,因為沒接過這樣的資料,後來查詢一些資料後才知道,前面是我得到的 key 值,透過 groupby 的方法已經幫我把同類型的資料內容分類好了,所以我已經得到了資料。
重點是怎麼渲染在畫面上
網路上找了許多方法,大部分都是告訴我怎麼用 groupby 重組資料,但比較少渲染在資料上,有找到的也無法完全符合我目前的情境。
後來觀察表格發現我要把目前同一個 key 的資料,有共同的內容要用 rowspan
的方式渲染在畫面上,不同的要維持原本的 table 呈現(如一開始畫面所示)。
跑雙迴圈
Object.keys()
- 得到重組資料後,一開始會得到一個物件裡面又包著我重組的陣列資料,想說去查一下物件怎麼轉成陣列的方法,後來去查,找不到,再換一個想法,就是如何取到物件中陣列的值,後來發現有一個 ES5 的語法是 Object.keys() 的方法,有成功取到值,但後來又卡住不知道怎麼渲染在畫面上,再去找資料。
keyValue
- 因為我知道要把資料渲染在畫面上,可以用
ngfor
來渲染資料,後來找到這篇,我把原本接 API 的內容替換成重組資料。並使用 Angular 的 pipe 方法,keyvalue,讓其跑迴圈時會遍歷資料所有的 key 跟 value。
後來才發現 groupby
組回來的資料外面是一個物件,因為物件沒有 forEach
可以用,但因透過 keyValue
的方式可以去找出物件的 key
跟 value
。
那 key
就是我的 CFID
,value
就是陣列。
來渲染網頁吧
僅記錄
tbody
的部分。
1 | <tbody> |
- 我把要共同顯示的部分用一個
ng-container
包起來,然後讓它跑第一層迴圈,並且後面使用keyvalue
這個 pipe 方法,讓我可以取到key
跟value
。這邊的 key 不用特別寫的原因是因為我在 groupby 的時候已經取出來了,所以使用keyvalue
時,會自己去抓到 key。 - 在
tr
上跑第二個迴圈,因為value
才是陣列資料本身的欄位,所以第二層迴圈是row.value
,這邊是小細節,必須注意,後來我也有用json pipe
的去檢查我取到的內容,才發現有value
這個欄位,在console
時不會看到。 - 在共同要顯示成一個欄位的
td
,我外層再使用一個ng-container
包起來,是要下判斷只取第二層迴圈的第一筆資料,原因是內容都一樣,只要選一個出來顯示即可,第二層迴圈才是真正的陣列資料。 - 在要上下合併的欄位使用
[attr.rowspan]="row.value.length"
去自訂義rowspan
的數值,期數值為該陣列資料的長度。
其他就讓它自己跑迴圈渲染,這樣就得到我要的畫面呈現了。