サンプル
動作イメージ
サンプルの動作イメージです。 日付を指定して「検索」ボタンをクリックすると、該当する日付を「完了予定日」に持つ商談の情報をdatatableに再レンダリングします。
コードと解説
このサンプルは Salesforce の LWC ( Lightning Web Component ) にて、@wireデコレータに紐付けたApexの呼び出し結果をリフレッシュするサンプルになっています。
someComponent.js
import { LightningElement, wire } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import getOpportunities from '@salesforce/apex/SomeController.getOpportunities';
const TODAY = new Date();
const COLUMNS = [
{ label: '取引先', fieldName: 'AccountUrl', type: 'url', typeAttributes: {label: { fieldName: 'AccountName' }, target: '_blank'}},
{ label: '商談', fieldName: 'OpportunityUrl', type: 'url', typeAttributes: {label: { fieldName: 'OpportunityName' }, target: '_blank'}}
];
export default class SomeComponent extends LightningElement {
wireExecCounter = 0;
error;
/** datatableのカラム設定 */
columns = COLUMNS;
/** Apex実行結果を再レンダリングに対応させるために、結果を保持する変数 */
wiredOpportunityResult;
get isLoading() {
return !this.wiredOpportunityResult.data && !this.wiredOpportunityResult.error;
}
/* 商談検索対象の日付 */
targetDate = this.formatDate(new Date(TODAY.getFullYear(), TODAY.getMonth(), TODAY.getDay()));
/* Apexコール結果の保持用 */
opportunities = [];
@wire(getOpportunities, { targetDate: '$targetDate', wireExecCounter: '$wireExecCounter' })
async wiredOpportunity(result) {
this.wiredOpportunityResult = result;
const { data, error } = result;
if ( data ) {
this.opportunities = await Promise.all(
data.map(async (opportunity) => {
const ret = {};
ret.Id = opportunity.Id;
if ( opportunity.AccountId ) {
ret.AccountName = opportunity.Account.Name;
ret.AccountUrl = `/${opportunity.AccountId}`;
}
ret.OpportunityName = opportunity.Name;
ret.OpportunityUrl = `/${opportunity.Id}`;
return ret;
})
);
this.error = undefined;
} else if ( error ) {
this.opportunities = [];
this.error = error;
}
}
/* datatableのデータクリア */
clearDatatable() {
this.wiredOpportunityResult.data = null;
this.wiredOpportunityResult.error = null;
this.opportunities = [];
}
/* 検索処理 */
search() {
this.clearDatatable();
this.wireExecCounter++; // wire関数の実行回数をインクリメントしてキャッシュを無効化
this.targetDate = this.template.querySelector('[data-id="targetDate"]').value;
refreshApex(this.wiredOpportunityResult);
}
/* 日付をYYYY-MM-DDの書式で返すメソッド */
formatDate(dt) {
var y = dt.getFullYear();
var m = ('00' + (dt.getMonth()+1)).slice(-2);
var d = ('00' + dt.getDate()).slice(-2);
return (y + '-' + m + '-' + d);
}
}
@wireデコレータで紐付けられてコールされるApexコードは次のようにしています。
SomeController.cls
public with sharing class SomeController {
@AuraEnabled(cacheable=true)
public static List<Opportunity> getOpportunities(Date targetDate) {
return [
SELECT
Id,
Name,
AccountId,
Account.Name
FROM
Opportunity
WHERE
CloseDate = :targetDate
];
}
}
テンプレートは次のようになります。
someComponent.html
<!-- sldsValidatorIgnore -->
<template>
<lightning-card title="検索">
<div>
<div class="row slds-align_absolute-center">
<lightning-input type="date" label="検索日付(完了予定日)" data-id="targetDate" value={targetDate}></lightning-input>
</div>
<div class="row slds-align_absolute-center" style="margin: 10px;">
<lightning-button label="検索" onclick={search} class="slds-button"></lightning-button>
</div>
</div>
</lightning-card>
<lightning-card title="実行">
<div class="bootstrap">
<div if:false={isLoading}>
<lightning-datatable
key-field="Id"
data={opportunities}
columns={columns}
>
</lightning-datatable>
</div>
<div if:true={isLoading} class="slds-spinner_inline spinner-padding">
<lightning-spinner
variant="brand"
alternative-text="Loading..."
size="medium"
>
</lightning-spinner>
</div>
</div>
</lightning-card>
</template>
ポイントはメンバ変数(JavaScriptコードの20行目)wiredOpportunityResult
を用意することです。この変数は@wireデコレータで紐付けたApexメソッド(SomeController.getOpportunities
)の実行結果をリフレッシュに対応させるために、Apexメソッドの実行結果を保持する変数です。
33行目の
this.wiredOpportunityResult = result;
で結果を保持させています。
このようにメンバ変数に結果を保持させておいた上で、再レンダリングによってリフレッシュしたい際にrefreshApex
メソッドにこの変数を渡すことで@wireデコレーションしたApexメソッドの再コールが行われます。サンプルでは64〜70行目のsearchメソッドにて、検索条件(targetDate)を再設定した後に
refreshApex(this.wiredOpportunityResult);
でApexメソッドの再コールが行われ、this.opportunities
への商談データの詰め込みが再度行われてdatatableがリフレッシュされます。
注意点
34行目でresult.data
とresult.error
を取り出しています。
const { data, error } = result;
このdata(result.data
)をメンバ変数にセットして、refreshApexメソッドに渡してもリフレッシュできそうに思ってしまいますが、できませんので注意してください。@wireデコレータで直接渡された引数(ここではresult
)をそのまま丸ごとメンバ変数にセットしておく必要があります。
その他のTips
このサンプルでは検索中のLoading表示をするサンプルにもなっています。
ローディング状態を判定するisLoading
を下記のように実装しています。
get isLoading() {
return !this.wiredOpportunityResult.data && !this.wiredOpportunityResult.error;
}
また、キャッシュを効かせずに確実にリフレッシュさせるために、wireExecCounter
というメンバ変数を用意して、Apexメソッドのコールをするたびにカウントアップして、Apexメソッドに対して異なる引数を呼び出すようにしています。