Skip to main content

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

学習の目的

この単元を完了すると、次のことができるようになります。

  • どのような場合に Apex を使用して Salesforce データを操作する必要があるかを認識する。
  • 2 つの異なる方法で Apex をコールする。
  • Apex と lightning-datatable を使用してレコードのリストを操作する。
メモ

メモ

日本語で受講されている方へ
このバッジの Trailhead ハンズオン Challenge は英語で受講していただく必要があります。英語の意味についてはかっこ内の翻訳をご参照ください。Trailhead Playground では (1) [Locale (地域)] を [United States (米国)] に、[Language (言語)] を [English (英語)] に切り替えて、(2) 英語の値のみをコピーして貼り付けてください。こちらの指示に従ってください。

翻訳版 Trailhead を活用する方法の詳細は、自分の言語の Trailhead バッジを参照してください。

Lightning Web コンポーネントでの Apex

Lightning データサービスのメリットと使用方法を学習しましたが、lightning-record-*-form コンポーネントも LDS ワイヤーアダプターや関数も適さない特定の使用事例がある場合もあります。たとえば、レコードデータが 1 件のトランザクションをカスタマイズする場合や、1 つのトランザクションで複数レコードの操作を実行する場合、Apex が最適です。

Lightning Web コンポーネントでの Apex の使用

Lightning Web コンポーネントで使用される Apex メソッドは staticpublicglobal のいずれかで、メソッド定義の直前に @AuraEnabled アノテーションが付加されている必要があります。@AuraEnabled アノテーションによって Apex メソッドを Lightning コンポーネント (Lightning Web コンポーネントと Aura コンポーネントの両方) で使用できるようになります。

フレームワークがデータをキャッシュできるようにすることで、サーバーコールの繰り返しがなくなり、以降の参照操作の実行が速くなります。@AuraEnabled アノテーションに cacheable = true と設定すると、メソッドがキャッシュ可能とマークされます。@AuraEnabled メソッドがキャッシュ可能の場合、データ操作言語 (DML) による操作は許可されません。次の例の行 2 では、getContactsBornAfter メソッドがキャッシュ可能と指定されています。

ContactController.cls

public with sharing class ContactController {
    @AuraEnabled(cacheable=true)
    public static List<Contact> getContactsBornAfter(Date birthDate) {
        return [
            SELECT Name, Title, Email, Phone
            FROM Contact
            WHERE Birthdate > :birthDate
            WITH SECURITY_ENFORCED
       ];
    }
}

メソッドがキャッシュ可能の場合、キャッシュが更新されるまで新しく追加または変更されたレコードのバージョンが返されません。次のセクションでキャッシュを手動で更新する方法を説明します。

LWC からの Apex メソッドコール

Lightning Web コンポーネントから Apex メソッドを操作するには、メソッドを結び付けるか、命令的にメソッドをコールするという 2 つの方法があります。両方のアプローチを考えてみましょう。

@wire を使用した Apex コール

Apex メソッドを結び付けるには、メソッドを cacheable にする必要があります。キャッシュ可能な Apex メソッドを結び付けるには、@wire デコレーターを使用します (LDS ワイヤーアダプターを使用する場合と同じ方法)。この方法で Apex をコールすると Lightning Web コンポーネントエンジンに制御が委任されてリアクティブサービスが作成されます。Apex メソッドに渡されるパラメーターの値が変わるたびに、Apex メソッドが実行され、デコレートされたプロパティまたは関数に新しい値がプロビジョニングされます。結び付けられたメソッドがキャッシュ可能である必要があるため、データは LDS キャッシュまたはサーバーから取得される可能性があります。Apex メソッドによってキャッシュされたデータを更新するには、refreshApex 関数をコールします。

注意: Lightning データサービスは、Apex メソッドによってキャッシュされたデータを認識しません。LDS 関数がレコードを更新すると、その更新は Apex メソッドによってキャッシュされたデータに影響を与えません。

次の例では @wire を使用して Apex をコールしています。このコードは、指定された生年月日より後に生まれた取引先責任者を取得します。

wireApexProperty.js

import { LightningElement, api, wire } from 'lwc';
import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter';
export default class WireApexProperty extends LightningElement {
    @api minBirthDate;
    @wire(getContactsBornAfter, { birthDate: '$minBirthDate' })
    contacts;
}

コードのポイント:

  • 行 2: getContactsBornAfter 関数を ContactController Apex クラスからインポートします。これは対応する Apex メソッドを参照します。
  • 行 4: @api minBirthDate プロパティを定義します。このコンポーネントをコード内で使用したり、FlexiPage 属性を公開したりする場合は、日付を @api minBirthDate プロパティに渡すことができます。
  • 行 5: @wire デコレーターが 2 つのパラメーター (コールする Apex メソッド (getContactsBornAfter) とアダプターに必要なパラメーター (birthDate)) を受け取ります。$minBirthDate をリアクティブ変数 (先頭が $) として渡します。
  • 行 6: 結果を contacts プロパティに保存します。
  • 行 5 ~ 6: 最初に Apex メソッドがデータを contacts プロパティにプロビジョニングし、そのデータを LDS キャッシュに保存します。$minBirthDate はリアクティブであるため、その値が変更されるたびに Apex メソッドが実行され、新しいデータがキャッシュまたはサーバーからプロビジョニングされます。

命令的な Apex コール

@wire を使用して Apex をコールする代わりに、命令的に Apex をコールすることもできます。参照操作の呼び出しを制御する必要がある場合とレコードを変更する場合は、命令的に Apex をコールします。Apex を命令的にコールするには、インポートした関数をコンポーネントの JavaScript ファイルから呼び出します。この関数は JavaScript promise を返します (LDS 関数を命令的にコールする場合と同様)。

キャッシュ可能な Apex メソッドとキャッシュ不能な Apex メソッドの両方を命令的にコールすることができます。ただし、キャッシュ可能な Apex メソッドを命令的に更新することはできません。代わりに、@wire を使用してメソッドをコールし、refreshApex で更新します。

callApexImperative.js の例では、ユーザーが .html ファイル内の lightning-button (ここには含まれていない) をクリックすると、handleButtonClick が命令的に getContactsBornAfter Apex メソッドをコールします。

callApexImperative.js

import { LightningElement, api, wire } from 'lwc';
import getContactsBornAfter from '@salesforce/apex/ContactController.getContactsBornAfter';
export default class CallApexImperative extends LightningElement {
    @api minBirthDate;
    handleButtonClick() {
        getContactsBornAfter({ //imperative Apex call
            birthDate: this.minBirthDate
        })
            .then(contacts => {
                //code to execute if related contacts are returned successfully
            })
            .catch(error => {
                //code to execute if related contacts are not returned successfully
            });
    }
}

コードのポイント:

  • 行 2: getContactsBornAfter 関数を ContactController クラスからインポートします。
  • 行 4: minBirthDate 公開プロパティを定義します。これで、このコンポーネントをコードで使用したり、FlexiPage 属性を公開したりする際に日付を渡すことができるようになります。
  • 行 6 ~ 7: handleButtonClick メソッドがフレームワークによって呼び出されると、getContactsBornAfter Apex メソッドを命令的に呼び出し、メソッドが指定された生年月日より後に生まれた取引先責任者を取得するのに必要な birthDate を渡します。
  • 行 9 ~ 14: 行 6 の命令的な Apex コールが promise を返します。Apex メソッドコールが成功した場合、promise が満たされ、then メソッドが実行されます。それ以外の場合、promise は却下され、catch メソッドが実行されます。

Lightning Web サービスでレコードのリストを操作するのに適しているのは、lightning-datatable 基本コンポーネントを使用する方法です。lightning-datatable を使用して、無限スクロール、インライン編集、ヘッダーおよび行レベルのアクション、サイズ変更などの機能を持つデータのテーブルを作成します。UI コンポーネントにはデータが入力されている必要があります。そのデータを生成するには、このモジュールですでに説明した方法のいずれかで Apex をコールするのが最も一般的な方法です。

レコードをテーブルにリストする Lightning Web コンポーネントのリリース

lightning-datatable に既存の取引先のリストを表示する例を操作しましょう。Apex と @wire を使用してレコードを取得します。

  1. AccountController という名前の Apex クラスを作成します。
    1. エクスプローラーペインで、classes フォルダーを右クリックして [SFDX: Create Apex Class (SFDX: Apex クラスを作成)] を選択します。
    2. クラス名として「AccountController」と入力し、Enter キーを押します。
    3. もう一度 Enter キーを押して、デフォルトのディレクトリを受け入れます。
  2. AccountController クラスの内容を次のコードで置き換えます。
    public with sharing class AccountController {
        @AuraEnabled(cacheable=true)
        public static List<Account> getAccounts() {
            return [
                SELECT Name, AnnualRevenue, Industry
                FROM Account
                WITH SECURITY_ENFORCED
                ORDER BY Name
            ];
        }
    }
    コードのポイント:
    • 行 2: メソッドに @AuraEnabled(cacheable=true) アノテーションを付加して、結果がキャッシュされるようにします。
    • 行 3: Apex で getAccounts メソッドを定義して、参照操作を実行して既存の取引先を取得します。
  3. accountList という名前の Lightning Web コンポーネントを作成します。
  4. accountList.js ファイルの内容を次のコードで置き換えます。
    import { LightningElement, wire } from 'lwc';
    import NAME_FIELD from '@salesforce/schema/Account.Name';
    import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue';
    import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';
    import getAccounts from '@salesforce/apex/AccountController.getAccounts';
    const COLUMNS = [
        { label: 'Account Name', fieldName: NAME_FIELD.fieldApiName, type: 'text' },
        { label: 'Annual Revenue', fieldName: REVENUE_FIELD.fieldApiName, type: 'currency' },
        { label: 'Industry', fieldName: INDUSTRY_FIELD.fieldApiName, type: 'text' }
    ];
    export default class AccountList extends LightningElement {
        columns = COLUMNS;
        @wire(getAccounts)
        accounts;
    }

    コードのポイント:
    • 行 2 ~ 4: 以前の例と同様に項目参照をインポートします。
    • 行 5: getAccounts 関数を AccountController クラスからインポートします。
    • 行 13: @wiregetAccounts 関数に使用してデータを取得します。
    • 行 14: 結果を accounts プロパティに保存します。操作が成功すると、レコードは accounts.data でアクセス可能になります。失敗するとエラーが account.error に表示されます。
  5. accountList.html ファイルの内容を次のコードで置き換えます。
    <template>
        <lightning-card>
            <template if:true={accounts.data}>
                <lightning-datatable
                    key-field="Id"
                    data={accounts.data}
                    columns={columns}
                >
               </lightning-datatable>
            </template>
        </lightning-card>
    </template>
    コードのポイント:
    • 行 4 ~ 9: lightning-datatable 基本コンポーネントを定義して、JavaScript ファイルに入力されている accounts.datacolumns を使用します。
  6. AccountController クラスを保存します。
  7. accountList.js-meta.xml の内容を次のコードで置き換えてコンポーネントをアプリケーションページで使用できるようにします。
    <?xml version="1.0" encoding="UTF-8"?>
    <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
        <apiVersion>48.0</apiVersion>
        <isExposed>true</isExposed>
        <targets>
            <target>lightning__AppPage</target>
        </targets>
    </LightningComponentBundle>
  8. 3 つのコンポーネントファイルをすべて保存します。
  9. force-app/main/default フォルダーを Trailhead Playground にリリースします。
  10. Trailhead Playground で、Lightning アプリケーションビルダーに移動し、[Working with Data (データの操作)] ページを開きます。
  11. accountList コンポーネントをページのメインの範囲にドラッグします。
  12. ページを保存します。
  13. [Working with Data (データの操作)] ページに戻って新しいコンポーネントを表示します。
メモ

lightning-datatable コンポーネントを使用するときには、次の点に留意してください。

  • 一部のデータ型は現在 lightning-datatable コンポーネントでサポートされていません。ただし、カスタムデータ型は使用できます。詳細は、ドキュメントで「Create Custom Data Types」 (カスタムデータ型の作成) までスクロールしてください。
  • lightning-datatable コンポーネントは現在モバイルでは動作しません。モバイルをサポートする必要がある場合は、代わりにカスタムテーブルを作成します。

Lightning Web コンポーネントで Salesforce データを操作するいくつかの方法を理解できました。次は、サーバーエラーが発生したときの処理方法を学習します。

リソース

無料で学習を続けましょう!
続けるにはアカウントにサインアップしてください。
サインアップすると次のような機能が利用できるようになります。
  • 各自のキャリア目標に合わせてパーソナライズされたおすすめが表示される
  • ハンズオン Challenge やテストでスキルを練習できる
  • 進捗状況を追跡して上司と共有できる
  • メンターやキャリアチャンスと繋がることができる