2
1

More than 1 year has passed since last update.

LWCでDatatableのソートと検索の実装

Last updated at Posted at 2022-10-30

要件

取引先画面に自作商談の関連リストを表示したいです。「全件表示」ボタンの代り、関連リストにソートと全件検索を機能する。

LWCのDatatableで関連リストを実装する
Auraバージョンの実装があるから、下記参照になる。
https://qiita.com/richard_hcq/items/087c8c89d4b1bbd93cd7

実装

Apex側

基本的に汎用のSelectメソッドを実装する。来るSoqlを実行し、SObjectのリストを返す。


public with sharing class CommonDmlUtil {

    @AuraEnabled(cacheable=true)
    public static List<SObject> commonSelectRecords(String strSql) {

        return Database.query(strSql);
       
    }
}

Html

point1 縦軸のスクロール

<div class="slds-scrollable_y" style="height:10rem">…</div>

source

dtableOppForAccount.html

<template>
    <lightning-card   
        icon-name="custom:custom66"
    >
        <h1 slot="title" style="font-size:14px">商談リスト({recCount})</h1>
        <div slot="actions">
                <div class="slds-form_horizontal slds-form slds-grid slds-wrap">
                <lightning-input value={keyword} 
                    class="slds-size_3-of-4"
                    placeholder="キーワード検索"
                    onchange={handleSearchMem}></lightning-input>
                <lightning-button-icon
                    class="slds-size_1-of-4"
                    icon-name="utility:search" ></lightning-button-icon>
                </div>
            </div>
        <div class="slds-scrollable_y" style="height:10rem">
            <template if:true={results}>
                <lightning-datatable
                    key-field="Sequence_Number__c"
                    data={data}
                    columns={columns}
                    sorted-by={sortedBy}
                    sorted-direction={sortedDirection}
                    onsort={sortColumns}
                    show-row-number-column
                >
                </lightning-datatable>
            </template>
        </div>
    </lightning-card>
</template>

Javascript

dtableOppForAccount.js


import { LightningElement,api, wire } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import commonSelectRecords from '@salesforce/apex/CommonDmlUtil.commonSelectRecords';

const COLS = [
    { label: '商談名', fieldName: 'linkName', type: 'url',
       typeAttributes: {label: { fieldName: 'Name' }},sortable: true },
    { label: 'フェース', fieldName: 'StageName'},
    { label: '金額', fieldName: 'Amount',
        type: 'number',cellAttributes: { alignment: 'left' } },
    { label: '取引先', fieldName: 'accountLinkName',type: 'url',
        typeAttributes: {label: { fieldName: 'Account.Name' }},sortable: true },
    { label: '終了予定日', fieldName: 'CloseDate' }    
];
export default class DtableOppForAccount extends LightningElement {
    columns = COLS;
    @api recordId; // parent id
    sortedDirection = 'asc';
    sortedBy = 'Name';
    results;
    data;
    recCount = 0;
    keyword = '';



    connectedCallback(){
    //exec
    var sql = 'Select '
        + ' Id, Name,StageName,'
        + '  Amount,'
        + ' AccountId,'
        + ' Account.Name,'
        + ' CloseDate'
        + ' From Opportunity'
        + " Where AccountId = '" +this.recordId +"'";
        + ' order by Name';
        console.log('test 1 sql>' + sql);
        commonSelectRecords({strSql: sql })
        .then(result => {
            //console.log('test 1 result>' + result);
           //this.results = result;
            
           // var a  = JSON.parse(JSON.stringify(this.results));
            var arr = [];
        
            for (var i = 0; i < result.length; i++) {
                console.log('1.5)'+(JSON.stringify(result[i])));
                var rec = {};
                var key = Object.keys(result[i]);
                for( var j = 0; j < key.length; j++ ) {
                    console.log('key )'+ key[j] + ' -- ' + result[i][key[j]]);
                    rec[ key[j] ] = result[i][ key[j] ];
                    if(key[j]=='Account'){
                        rec['Account.Name'] =  result[i][ key[j] ].Name;
                    }
                }
                rec['linkName'] = '/' + result[i].Id;
                rec['accountLinkName'] = '/' + result[i].AccountId;
                arr.push(rec);
             }
             this.results =  arr;
             this.data = arr;
             this.recCount = arr.length;
             //console.log('2)'+JSON.stringify(this.results ));
        })
        .catch(error => {
            /*eslint no-console: "off"*/
            console.log(error);
            this.result = error;
            this.dispatchEvent( new ShowToastEvent({
                title: '処理結果',
                message: 'レコード取得が失敗しました。\n' + error.body.message,
                variant: 'error',
                mode: 'dismissable'
            }));
        })

    }

    sortColumns( event ) {
        this.sortedBy = event.detail.fieldName;
        
        this.sortedDirection = event.detail.sortDirection;
        var reverse = this.sortedDirection !== 'asc';
        let arr = this.results;
        //console.log('data -- ' + JSON.stringify(arr[0]));
        arr.sort(this.sortBy(this.sortedBy, reverse))
        this.data = [...arr];
        
        //return this.results;
        
    }

    sortBy(fieldname, reverse, primer) {
        var key = primer ?
            function(x) {return primer(x[fieldname])} :
            function(x) {return x[fieldname]};
            reverse = !reverse ? 1 : -1;
        return function (a, b) {
            return a = key(a)?key(a):'', b = key(b)?key(b):'', reverse * ((a > b) - (b > a));
        }
    }
    
    handleSearchMem(event) {
        this.keyword = event.target.value;
        var term = this.keyword;
        var arr = this.results;
        console.log('term >' + term);
        var regex = new RegExp(term, "i");
        try {
            //console.log('arr: ' + JSON.stringify(arr));
            var tmpData = arr.filter(row=>regex.test(row['Name']));
            //console.log('tmpData: ' + JSON.stringify(tmpData));
            this.data = [...tmpData];
            this.recCount = this.data.length;
        }catch(e){
            alert(e);
        }
        

    }
}

point2 複合名前の値の取る方法(例 AccountId.Name)

Dataがサーバから帰ってるとき、順番に取り出し、複合名前のコルムを作成し、値を設定する

 if(key[j]=='Account'){
      rec['Account.Name'] =  result[i][ key[j] ].Name;
 }

point3 dataに値だけを変更されても、画面に再描写されない。

メモリが再設定する

this.data = [...arr];

point4 sort and seach

やり方はあまりわからないですが、どうかコピーされて使える

結果

sort機能と快速検索が効く、素早く感じです。
問題は件数が何万件以上は、Limit件数が入れ、サーバ側の再検索がいります。(ToDo)
image.png

追記① Lightning search

検索のところは自分で検索アイコンとインプットの組み合わせで実現したが、実際SalesforceのSearchのインプットがある。入れ替えると下記になる(コメント付き)。

       <div slot="actions">
            <div class="slds-form_horizontal slds-form slds-grid slds-wrap">
                    <lightning-input type="search" 
                    label="" 
                    placeholder="フリーワード" 
                    value={keyword} 
                    onchange={handleSearchMem} 
                    onkeydown={handleSearchDB}>
                </lightning-input>
            </div>
            <div style="font-size:12px">
                検索可能項目:店舗名/共通ID/会社名/ショップコード
            </div>
        </div

image
image.png

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1