技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Salesforce 開発者の JavaScript スキル(10)

Prepare for your Salesforce JavaScript Developer I Credential Trailmix

コレの続き。

Lightning Web コンポーネントSalesforce データ

Lightning データサービスを使用したデータの操作

trailhead.salesforce.com

まぁ単純に作る系のお話。

  • LWC(Name: ContactCreator) 作って
  • コンポーネントではオブジェクトとフィールド名を用意。保存完了時に toast (画面↑に緑の帯で出るメッセージ)表示

オブジェクトのフィールド定義系

// Object
import CONTACT_OBJECT from '@salesforce/schema/Contact';
// Fields
import FIRST_NAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LAST_NAME_FIELD from '@salesforce/schema/Contact.LastName';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';

// 中略
    objectApiName = CONTACT_OBJECT;
    fields = [FIRST_NAME_FIELD, LAST_NAME_FIELD, EMAIL_FIELD];
  • 保存成功時は toast で表示する
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

// 中略
    handleSuccess(event) {
        const toastEvent = new ShowToastEvent({
            title: "Account created",
            message: "Record ID: " + event.detail.id,
            variant: "success"
        });
        this.dispatchEvent(toastEvent);
    }
        <lightning-record-form
            object-api-name={objectApiName}
            fields={fields}
            onsuccess={handleSuccess}>
        </lightning-record-form>
  • 最後に Lightning App Builder で登録できるようにして登録
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target><!-- アプリケーションページで使いますよー宣言 -->
    </targets>
</LightningComponentBundle>

ちなみに、これで一旦レコード作ってしまうと、再編集しても保存後の表示が変わらない…
キャッシュ機構があると思われるので、

refreshValues() {
    const inputFields = this.template.querySelectorAll('lightning-input-field');
    if (inputFields) {
        inputFields.forEach((field) => {
            field.reset();
        });
    }
}

で強制的にリフレッシュしてもいいし、レコード状態が変化したことを Salesforce経由で通知 してもいい

Apex を使用したデータの操作

trailhead.salesforce.com

内容的にはApex メソッドを @wire でバインドして表示するだけの課題。

  • ざっくりApexコードを作って
public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContacts(){
        // 支持に従うSELECT文
    }
}
import { LightningElement, wire } from 'lwc';
import FIRST_NAME_FIELD from '@salesforce/schema/Contact.FirstName';
import LAST_NAME_FIELD from '@salesforce/schema/Contact.LastName';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
import getContacts from '@salesforce/apex/ContactController.getContacts';

const COLUMNS = [
    { label: 'First Name', fieldName: FIRST_NAME_FIELD.fieldApiName, type: 'text' },
    { label: 'Last Name', fieldName: LAST_NAME_FIELD.fieldApiName, type: 'text' },
    { label: 'Industry', fieldName: EMAIL_FIELD.fieldApiName, type: 'text' }
];

export default class ContactList extends LightningElement {
    columns = COLUMNS;

    @wire(getContacts)
    contacts;
}
  • Datatable で表示する
        <template if:true={contacts.data}>
            <lightning-datatable
                key-field="Id"
                data={contacts.data}
                columns={columns}
            >
           </lightning-datatable>
        </template>
  • XML 設定を書いて画面配置して終了
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
    </targets>
</LightningComponentBundle>

サーバエラーの処理

trailhead.salesforce.com

Apex で取得時に例外が発生した時にそれを画面上表示する機能の追加課題。

  • Controller で例外を吐くよう置き換え
public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContacts(){
        throw new AuraHandledException('Forced error');
    }
}
  • ldsUtils を移植します。ソースは ここ ですね。
    テンプレートのHTMLを削除し、ソースをコピーすればOKです。(こんな感じでLWC以外のJsもコンポーネントとして配置できます)
  • これを使って errors の getter を作成します。
import { LightningElement, wire } from 'lwc';
// 中略
import { reduceErrors } from 'c/ldsUtils';

// 中略

export default class ContactList extends LightningElement {
    // 中略
    get errors() {
        return (this.contacts.error) ?
            reduceErrors(this.contacts.error) : [];
    }
}
  • テンプレートにエラー時の表示書いて完了
        <template if:true={errors}>
            <p>{errors}</p>
        </template>