進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

Salesforce CLI を使用した地理位置情報アプリケーションの作成

学習の目的

この単元を完了すると、次のことができるようになります。
  • CLI を使用して Apex クラスを作成する方法を説明する。
  • CLI コマンドを使用して Aura コンポーネントを作成する方法を説明する。

作成する内容

ここでは、機能、つまり地理位置情報アプリケーションを作成するために、ローカルでコードを記述し、スクラッチ組織に同期して、そこでテストします。その過程で、Apex といくつかの Aura コンポーネントを使用します。

新しいこと (Salesforce CLI、スクラッチ組織) に引き続き焦点を絞るために、Trailhead のプロジェクト「【Develop an Account Geolocation App with Aura Components|Aura コンポーネントを使用した取引先地理位置情報アプリケーションの開発】」のコードを再利用します。そのプロジェクトのステップの多くを繰り返しますが、適宜 CLI を使用します。すべてのコードはこのモジュールに記載してあるため、ページを行き来する必要はありません。

次の図は、コンポーネントのインタラクションの概要を示しています。ユーザが検索を実行したときのフロー制御図

この設計により、アプリケーションは柔軟で管理しやすいものになります。アプリケーションやビジネス要件の進化に合わせて、データを表示するコンポーネントを置き換えることができ、データをクエリするコンポーネントを作り直す必要はありません。また、この設計では、これらのコンポーネントを他のアプリケーションで個別に再利用できます。

  1. 取引先検索コンポーネントは、サーバ側のアクションをコールして取引先を検索します。
  2. Apex メソッドは、SOSL 検索結果を返します。
  3. 取引先検索コンポーネントは、データの他のコンポーネントに通知するイベントを起動します。
  4. イベントを処理するコンポーネントは、ユーザにデータを表示します。

取引先検索 Apex コントローラの作成

このステップでは、Apex コントローラを作成して Aura コンポーネントが取引先とその位置情報のリストを取得できるようにします。Apex クラスは、force-app/main/defaultclasses というフォルダに保存されます。CLI を使用して、新しい Apex クラスのスキャフォールディングをすばやく行うことができます。

  1. geolocation プロジェクトディレクトリ内で、プロジェクトのルートから次のコマンドを実行します。
    sfdx force:apex:class:create -n AccountSearchController -d force-app/main/default/classes
  2. AccountSearchController.cls を開き、スキャフォールディングコードを次のコードに置き換え、ファイルを保存します。
    public with sharing class AccountSearchController {
        @AuraEnabled
        public static List<Account> searchAccounts( String searchTerm ) {
            List<Account> accounts = new List<Account>();
            if ( String.isNotBlank( searchTerm ) ) {
                List<List<SObject>> searchResults = [
                    FIND :searchTerm
                    RETURNING Account(
                        Id, Name, Phone, Website,
                        BillingStreet, BillingCity,
                        BillingState, BillingPostalCode
                        ORDER BY Name
                        LIMIT 10
                    )
                ];
                accounts = searchResults[0];
            }
            return accounts;
        }
    }
  3. ここで、新しいコードをスクラッチ組織に転送 (同期) します。
    sfdx force:source:push
    force:source:push コマンドからの出力は、次のようになります。
    === Pushed Source
    STATE  FULL NAME               TYPE        PROJECT PATH
    ─────  ─────────────────       ──────────  ───────────────────────────────────────
    Add    AccountSearchController ApexClass   force-app/.../AccountSearchController.cls
    Add    AccountSearchController ApexClass   force-app/.../AccountSearchController.cls-meta.xml

    これで、スクラッチ組織が AccountSearchController によって更新されました。

取引先が読み込まれた Aura イベントの作成

単一責任の設計原則を使用して、検索結果の表示は、後のステップで作成する取引先地図コンポーネントと取引先リストコンポーネントによって処理されるイベントを起動することによって委任します。

  1. aura フォルダにイベントを作成します。
    sfdx force:lightning:event:create -n AccountsLoaded -d force-app/main/default/aura
  2. AccountsLoaded.evt を開き、内容を次のコードに置き換え、ファイルを保存します。
    <aura:event type="APPLICATION">
        <aura:attribute name="accounts" type="Account[]"/>
    </aura:event>
    
  3. 新しいコードをスクラッチ組織に転送します。
    sfdx force:source:push

    force:source:push コマンドからの出力は、次のようになります。

    === Pushed Source
    STATE FULL NAME                         TYPE                 PROJECT PATH
    ───── ───────────────────────────────── ──────────────────── ──────────────────────────────────────────────────────
    Add   AccountsLoaded/AccountsLoaded.evt AuraDefinitionBundle force-app/.../AccountsLoaded/AccountsLoaded.evt
    Add   AccountsLoaded/AccountsLoaded.evt AuraDefinitionBundle force-app/.../AccountsLoaded/AccountsLoaded.evt-meta.xml

取引先検索 Aura コンポーネントの作成

次に、これとほぼ同じプロセスを繰り返して、AccountSearch コンポーネントを作成します。Aura コンポーネントファイルは、バンドルにまとめられていて、force-app/main/default/aura フォルダ内のフォルダに保存されています。Apex クラスと同様に、コマンドラインから Aura コンポーネントのスキャフォールディングを行うことができます。

  1. aura フォルダにコンポーネントを作成します。
    sfdx force:lightning:component:create -n AccountSearch -d force-app/main/default/aura

    このように、すべての必要なファイルが作成されます。

    Visual Studio Code で、AccountSearch フォルダが展開され、ファイルが表示されています。
  2. AccountSearch.cmp を開き、内容を次のコードに置き換え、ファイルを保存します。
    <aura:component controller="AccountSearchController">
        <aura:registerEvent name="accountsLoaded" type="c:AccountsLoaded"/>
        <aura:handler name="init" value="{!this}" action="{!c.onInit}"/>
        <aura:attribute name="searchTerm" type="String" default="San Francisco"/>
        <lightning:card title="Account Search" iconName="standard:search">
            <div class="slds-form slds-p-around_x-small">
                <lightning:input
                    label="Search"
                    variant="label-hidden"
                    value="{!v.searchTerm}"
                    placeholder="Search by name, phone, website, or address"
                    onchange="{!c.onSearchTermChange}"/>
            </div>
        </lightning:card>
    </aura:component>

    このコンポーネントには、ユーザが取引先の名前や住所などの検索語を入力する入力項目があり、コンポーネントが初期化されたときや検索語が変更されたときにイベントハンドラを登録します。

  3. AccountSearchController.js を開き、内容を次のコードに置き換え、ファイルを保存します。
    ({
        onInit: function( component, event, helper ) {
            // proactively search on component initialization
            var searchTerm = component.get( "v.searchTerm" );
            helper.handleSearch( component, searchTerm );
        },
    
        onSearchTermChange: function( component, event, helper ) {
            // search anytime the term changes in the input field
            var searchTerm = component.get( "v.searchTerm" );
            helper.handleSearch( component, searchTerm );
        }
    })

    クライアント側コントローラは、コンポーネントの初期化イベントと検索語が変更された場合の処理を実行します。ヘルパーファイルをコールして、ユーザの入力に基づいて検索を実行します。

  4. AccountSearchHelper.js を開き、内容を次のコードに置き換え、ファイルを保存します。
    ({
        // code in the helper is reusable by both
        // the controller.js and helper.js files
        handleSearch: function( component, searchTerm ) {
            var action = component.get( "c.searchAccounts" );
            action.setParams({
                searchTerm: searchTerm
            });
            action.setCallback( this, function( response ) {
                var event = $A.get( "e.c:AccountsLoaded" );
                event.setParams({
                    "accounts": response.getReturnValue()
                });
                event.fire();
            });
            $A.enqueueAction( action );
        }
    })
  5. 新しいソースをスクラッチ組織に転送します。
    sfdx force:source:push
定義バンドルがスクラッチ組織に転送されています。
=== Pushed Source
STATE FULL NAME                                TYPE                 PROJECT PATH
───── ──────────────────────────────────────── ──────────────────── ──────────────────────────────────────────────────────
Add   AccountSearch/AccountSearch.auradoc      AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.auradoc
Add   AccountSearch/AccountSearch.cmp          AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.cmp
Add   AccountSearch/AccountSearch.cmp          AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.cmp-meta.xml
Add   AccountSearch/AccountSearch.css          AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.css
Add   AccountSearch/AccountSearch.design       AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.design
Add   AccountSearch/AccountSearch.svg          AuraDefinitionBundle force-app/.../AccountSearch/AccountSearch.svg
Add   AccountSearch/AccountSearchController.js AuraDefinitionBundle force-app/.../AccountSearch/AccountSearchController.js
Add   AccountSearch/AccountSearchHelper.js     AuraDefinitionBundle force-app/.../AccountSearch/AccountSearchHelper.js
Add   AccountSearch/AccountSearchRenderer.js   AuraDefinitionBundle force-app/.../AccountSearch/AccountSearchRenderer.js

取引先リスト Aura コンポーネントの作成

次に、データテーブルに取引先を表示する Aura コンポーネントを作成します。表示するデータを特定するために、このコンポーネントは前のステップで作成した c:AccountsLoaded イベントに登録します。

  1. aura フォルダにコンポーネントを作成します。
    sfdx force:lightning:component:create -n AccountList -d force-app/main/default/aura
  2. AccountList.cmp を開き、内容を次のコードに置き換え、ファイルを保存します。
    <aura:component>
        <aura:handler event="c:AccountsLoaded" action="{!c.onAccountsLoaded}"/>
        <lightning:navigation aura:id="navigation"/>
        <aura:attribute name="rows" type="Map[]"/>
        <aura:attribute name="cols" type="Map[]"/>
        <lightning:card title="Account List" iconName="standard:account">
            <lightning:datatable
                data="{!v.rows}"
                columns="{!v.cols}"
                keyField="Id"
                hideCheckboxColumn="true"
                showRowNumberColumn="true"
                onrowaction="{!c.onRowAction}"/>
        </lightning:card>
    </aura:component>

    このコンポーネントは AccountsLoaded イベントをリスンし、イベントデータをテーブルに表示します。ユーザが検索を行って別の結果が検出されると、リストはそれに応じて更新されます。

  3. AccountListController.js を開き、内容を次のコードに置き換え、ファイルを保存します。
    ({
        onAccountsLoaded: function( component, event, helper ) {
            var cols = [
                {
                    'label': 'Name',
                    'fieldName': 'Name',
                    'type': 'text'
                },
                {
                    'label': 'Phone',
                    'fieldName': 'Phone',
                    'type': 'phone'
                },
                {
                    'label': 'Website',
                    'fieldName': 'Website',
                    'type': 'url'
                },
                {
                    'label': 'Action',
                    'type': 'button',
                    'typeAttributes': {
                        'label': 'View details',
                        'name': 'view_details'
                    }
                }
            ];
            component.set( 'v.cols', cols );
            component.set( 'v.rows', event.getParam( 'accounts' ) );
        },
    
        onRowAction: function( component, event, helper ) {
            var action = event.getParam( 'action' );
            var row = event.getParam( 'row' );
            if ( action.name == 'view_details' ) {
                var navigation = component.find( 'navigation' );
                navigation.navigate({
                    'type': 'standard__recordPage',
                    'attributes': {
                        'objectApiName': 'Account',
                        'recordId': row.Id,
                        'actionName': 'view'
                    }
                });
            }
        }
    })

    クライアント側コントローラの onAccountsLoaded 関数は、イベントデータを <lightning:datatable> コンポーネントで想定される形式に変換します。onRowAction 関数は、ユーザが操作した行の取引先レコードに移動します。

  4. 新しいコードをスクラッチ組織に転送します。
    sfdx force:source:push