Salesforce LWC學習(十八) datatable展示 image

zero.zhang發表於2020-06-28

本篇參看:

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.

selectedRows獲取選中的行的資訊,另外一種就是找到datatable然後呼叫其getSelectedRows方法。

除此之外,我們看到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開發者可以養成獨立思考的能力,先思考,在查,最後再問。加油!

相關文章