本篇參看:
https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/documentation
https://www.lightningdesignsystem.com/components/data-tables/
我們在salesforce中,經常會使用 listview,標准的 lightning listview會有排序,filter展示chart等等標准功能。當然,某些情況標准搞定不了情況下,我們便需要使用自定義的開發。自定義開發我們就可以使用 lightning-datatable組件。一個 lightning-datatable組件用來展示表格數據,它可以根據數據類型展示每一列。比如一個 email類型的字段會展示一個點開以后是一個 mail:to的超鏈接。默認展示的類型是text類型。那 lightning-datatable有哪些特性呢?
- 展示和格式化焗油適當類型的列
- 具有無限滾動行功能
- 指定的數據類型允許 inline編輯
- 可以定義header的action
- 可以定義行級別的action
- 重置每一列展示的大小
- 選擇行操作
- 指定的列通過升序或者降序排列
- 文字換行和剪切
- 對行進行編號
- 設置單元格對齊方式
lightning-datatable有很多屬性,其他的請自行查看文檔,這里只例舉幾個核心屬性或者方法。比較核心的如下:
- columns:一組列的object用來定義數據類型,這個object有很多的屬性,其中有幾個必填的配置: label & fieldName & type。分別對應着字段的展示名稱,字段的API name以及字段的類型,不同的字段類型將會自動的轉換成不同的展示形式,默認是text。其他的屬性我們后期會有簡單介紹。
- data:一組數據用來展示,通常 comulns設置表單的頭以及每個單元列的類型,data設置內容;
- hide-checkbox-column:標簽用來設定是否展示左側的checkbox,值為true/false,true即隱藏checkbox;
- selected-rows:用來初始化時展示哪些行是被選中的;
- key-field:用來指定每行的unique id;
- getSelectedRows:這個是lightning-datatable提供的方法,用來獲取哪些行用戶選中的。
簡單介紹完畢,下面通過幾點來慢慢帶入datatable的功能。
一. 基礎 Datatable展示數據
demo中展示,我們來看官方提供的一個demo。
dataTableExample1.html:用來展示一個 datatable,我們看到屬性中的data / columns / key-field都是上面描述過的, onrowselection方法為當有行選擇的時候的調用
<template> <lightning-datatable data={data} columns={columns} key-field="id" onrowselection={getSelectedName}> </lightning-datatable> </template>
dataTableExample1.js:有兩種方式可以獲取選擇的行信息,demo中有兩個。datatable有一個標准事件rowselection,調用以后可以通過event.detail.
除此之外,我們看到columns的設置方式,除了 label / fieldName / type這三個基礎信息以外,還可以看到有 typeAttributes 以及 cellAttributes兩種設置。
- typeAttributes:用於對指定的列的類型格式化dataCell,不同的type可能擁有不同的設置。salesforce針對不同的type可以設置不同的 typeAttributes,這里不再詳細展開,具體查看文檔;
- cellAttributes:typeAttributes用於設置針對 type的格式化,cellAttributes通常用於列中附加圖標信息,設置圖標位置等信息。
import { LightningElement } from 'lwc'; const columns = [ {label: 'Opportunity name', fieldName: 'opportunityName', type: 'text'}, {label: 'Confidence', fieldName: 'confidence', type: 'percent', cellAttributes:{ iconName: { fieldName: 'trendIcon' }, iconPosition: 'right' }}, {label: 'Amount', fieldName: 'amount', type: 'currency', typeAttributes: { currencyCode: 'EUR'}}, {label: 'Contact Email', fieldName: 'contact', type: 'email'}, {label: 'Contact Phone', fieldName: 'phone', type: 'phone'}, ]; const data = [{ id: 'a', opportunityName: 'Cloudhub', confidence: 0.2, amount: 25000, contact: 'jrogers@cloudhub.com', phone: '2352235235', trendIcon: 'utility:down' }, { id: 'b', opportunityName: 'Quip', confidence: 0.78, amount: 740000, contact: 'quipy@quip.com', phone: '2352235235', trendIcon: 'utility:up' }]; export default class DatatableExample1 extends LightningElement { data = data; columns = columns; getSelectedName(event) { //兩種方式獲取選中的行,第一種是使用 event.detail.selectedRows,另外一種是使用querySelector找到 lightning-datatable,然后使用datatable封裝的方法 //const selectedRows = event.detail.selectedRows; const dataTable = this.template.querySelector('lightning-datatable'); const selectedRows = dataTable.getSelectedRows(); // Display that fieldName of the selected rows for (let i = 0; i < selectedRows.length; i++){ console.log("You selected: " + selectedRows[i].opportunityName); } } }
簡單展示效果如下:
二. datatable中展示父表中的字段值
上個demo中簡單介紹了datatable的使用,數據全是寫死的demo,接下來通過一個包含后台的邏輯進行datatable展示數據。
DataTableExampleController:用於獲取 Case表中的相關字段以及其父表的字段
public with sharing class DataTableExampleController { @AuraEnabled(cacheable=true) public static List<Case> getCaseList(){ List<Case> caseList = [SELECT Id,CaseNumber,Account.Name, Priority,Status FROM Case LIMIT 100]; return caseList; } }
datatableExample2.js:用於展示相關的字段,通過wire adapter獲取后台數據放在data中
import { LightningElement, track, wire } from 'lwc'; import getCaseList from '@salesforce/apex/DataTableExampleController.getCaseList'; const COLUMNS = [ {label: 'Case Number', fieldName: 'CaseNumber', type: 'text'}, {label: 'Account Name', fieldName: 'Account.Name', type: 'text'}, {label: 'Priority', fieldName: 'Priority', type: 'text'}, {label: 'Status', fieldName: 'Status', type: 'text'} ]; export default class DataTableExample2 extends LightningElement { columns = COLUMNS; @track datas; @wire(getCaseList) wiredCaseList({ error, data }) { if(data) { this.datas = data; } else if(error) { //TODO console.log(JSON.stringify(error)); } } }
dataTableExample.html:展示datatable
<template> <lightning-datatable data={datas} columns={columns} key-field="id" > </lightning-datatable> </template>
結果展示:通過下圖我們可以看到,其他的字段可以正常展示,但是父表的數據獲取確實失敗的。
來剖析一下原因,datatable針對columns的fieldName只支持一級結構的獲取,針對獲取父的方式沒法通過 各種點的方式獲取到,那么如何獲取呢,查看下面的方式,我們對js的代碼進行一下改動。按照下面的步驟兩步走的修改。
結果展示:我們可以看到 Account Name列的值也順利的展示出來了,按照這種操作做一個拓展,其實我們也可以去做一些字段間的邏輯操作拼出一個符合我們邏輯的列,不僅僅局限於獲取父的對象值這種簡單操作。
三. 實現datatable展示 formula類型是圖片的功能
自己看文檔的小伙伴可能發現datatable的columns的type沒有類似 image類型,但是在object field創建時我們很容易創建一些IMAGE的字段,那樣的話使用標准的datatable便無法展示,那要如何操作呢?還好lwc提供了一個自定義類型的操作。首先我們在Case表里面新增一個formula 字段,展示圖片。
接下來一步接着一步搞定。
dataTableWithImage.js:這里需要繼承 LightningDatatable,並且引入 imageRow.html,其用於做template
import LightningDatatable from 'lightning/datatable'; import imageRow from './imageRow.html'; export default class DataTableWithImage extends LightningDatatable { static customTypes = { image: { template: imageRow } }; }
imageRow.html:默認要求 imageRow需要和 dataTableWithImage在同一個目錄下,如果不在一個目錄,需要改上面的文件目錄信息。
<template> <c-data-table-image-template url={value} > </c-data-table-image-template> </template>
dataTableImageTemplate.html:用來通過 img標簽展示圖片
<template> <img src={url} class="image"/> </template>
dataTableImageTemplate.css:用來設置圖片大小的初始值,這種是一種偷懶的方式,正常應該通過 attribute注入進來指定大小的寬和高。
.image { height: 30px; width: 30px; }
dataTableImageTemplate.js
import { LightningElement,api } from 'lwc'; export default class DataTableImageTemplate extends LightningElement { @api url; }
OK,通過上面的這些步驟我們實現和繼承了自定義的datatable組件。接下來是調用操作。我們在class里面搜索一下Priority_Image__c這個字段,apexClass這里不再寫。
dataTableExample3.js:這里有幾個關鍵點。
- 設置 type為 image類型,image類型是我們上文自定義創建的
- 對 formula類型進行解析,找到他的src部分。比如針對<img src="/resource/priority/priority/medium.png" alt="Priority Flag" border="0"/>這個字符串,我們需要的是/resource/priority/priority/medium.png這個字符串
import { LightningElement, track, wire } from 'lwc'; import getCaseList from '@salesforce/apex/DataTableExampleController.getCaseList'; const COLUMNS = [ {label: 'Case Number', fieldName: 'CaseNumber', type: 'text'}, {label: 'Account Name', fieldName: 'AccountName', type: 'text'}, {label: 'Priority', fieldName: 'Priority', type: 'text'}, { label: 'Priority Image',fieldName:'Priority_Image__c',type: 'image' }, {label: 'Status', fieldName: 'Status', type: 'text'} ]; export default class DataTableExample3 extends LightningElement { columns = COLUMNS; @track datas; @wire(getCaseList) wiredCaseList({ error, data }) { if(data) { //this.datas = data; let resultList = []; let objectTemp; data.forEach(item => { objectTemp = Object.assign({},item); if(item.Account) { objectTemp.AccountName = item.Account.Name; } const srcIndex = objectTemp.Priority_Image__c.indexOf('src='); if(srcIndex !== -1) { const imgSrcSubstring = objectTemp.Priority_Image__c.substring(srcIndex + 5); objectTemp.Priority_Image__c = imgSrcSubstring.substring(0,imgSrcSubstring.indexOf('"')) } console.log(JSON.stringify(objectTemp)); resultList.push(objectTemp); }); this.datas = resultList; } else if(error) { //TODO console.log(JSON.stringify(error)); } } }
dataTableExample3.html
<template> <c-data-table-with-image key-field="id" data={datas} columns={columns} > </c-data-table-with-image> </template>
結果展示:針對不同的Priority展示其對應的formula的圖片。
總結:篇中講了datatable的簡單的應用以及相應的擴展,datatable很強悍,這里不逐點講述,感興趣的可以自行查看 inline edit,action等操作。篇中有錯誤地方歡迎指出,有不懂的歡迎留言。
后記:工作原因這篇博客准備了好久才成型,不知不覺學了半年的lwc的開發,也整理總結了一些博客供自己和他人學習。前半年的主旋律大部分時間都在學習lwc,后半年的時間大部分會放在考證和學習其他技術,不出意外應該是今年的最后一篇lwc的博文。有其他lwc的問題歡迎留言探討,希望各位salesforce開發者可以養成獨立思考的能力,先思考,在查,最后再問。加油!