Tune in to Trailblazers Innovate for Salesforce product news,
demos, and latest roadmaps. Register here.
close
進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

標準リストコントローラの使用

学習の目的

この単元を完了すると、次のことができるようになります。
  • Visualforce 標準リストコントローラとは何か、標準 (レコード) コントローラとの違いは何かを説明する。
  • 標準リストコントローラで提供される、標準コントローラとは異なるアクションを 3 つ挙げる。
  • Visualforce ページで標準リストコントローラを使用して、レコードのリストを表示する。
  • ページネーションを定義して Visualforce ページに追加する。

標準リストコントローラの概要

標準リストコントローラを使用すると、レコードセットの表示や操作が行える Visualforce ページを作成できます。

レコードのリストの表示は、ほぼすべての Web アプリケーションの基本動作です。Visualforce では、バックエンドコードなしでマークアップのみを使用して、同じタイプのレコードのリストを非常に簡単に表示できます。この秘密の鍵は標準コントローラにあり、この場合は標準リストコントローラが使用されます。

標準リストコントローラには、特定のオブジェクトレコードのクエリ、コレクション変数でのレコードの使用、および結果の絞り込みやページネーションなど、多数の強力な自動動作があります。ページへの標準リストコントローラの追加は標準 (レコード) コントローラの追加と非常に似ていますが、一度に 1 レコードを操作する代わりに、一度に多数のレコードを操作することを目的としています。

レコードのリストの表示

<apex:pageBlockTable> などの標準リストコントローラおよび反復コンポーネントを使用して、レコードのリストを表示します。

標準 (レコード) コントローラにより、Visualforce ページで使用できる変数に 1 つのレコードを簡単に読み込むことができます。標準リストコントローラも同様ですが、1 つのレコードの代わりに、レコードのリストまたはコレクションを変数に読み込みます。

個々のレコードではなくコレクションを操作するため、反復コンポーネントを使用してレコードを表示する必要があります。反復コンポーネントは、1 つの値ではなく類似した項目のコレクションと連動します。反復コンポーネントはそのコレクションをループし、各レコードに対して、コンポーネントマークアップの一部として提供するテンプレートに基づいて出力を生成します。これは複雑に思えるかもしれませんが、マークアップを読めばすぐに理解できます。

標準リストコントローラを使用するためのマークアップは、一度に 1 レコードの標準コントローラを使用するためのマークアップとほぼ同じです。その違いを明確にするため、次のサンプルでは主な違いが太字で強調表示されています。

  1. 新しい Visualforce ページを作成するには、開発者コンソールを開き、[File (ファイル)] | [New (新規)] | [Visualforce Page (Visualforce ページ)] をクリックします。ページ名に「Contact List」と入力します。
  2. エディタで、任意のマークアップを次のように置き換えます。
    <apex:page standardController="Contact" recordSetVar="contacts">
        <apex:pageBlock title="Contacts List">
            <!-- Contacts List -->
            <apex:pageBlockTable value="{! contacts }" var="ct">
                <apex:column value="{! ct.FirstName }"/>
                <apex:column value="{! ct.LastName }"/>
                <apex:column value="{! ct.Email }"/>
                <apex:column value="{! ct.Account.Name }"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:page>
  3. [Preview (プレビュー)] をクリックして、変更処理中に確認できるページのプレビューを開きます。標準の Salesforce ページヘッダー、サイドバー要素、取引先責任者のリストが表示された新規ウィンドウが開きます。標準リストコントローラによる取引先責任者のリスト

標準リストコントローラの使用方法は、標準コントローラの使用方法によく似ています。最初に <apex:page> コンポーネントの standardController 属性を設定し、次に同じコンポーネントの recordSetVar 属性を設定します。standardController 属性では、標準コントローラと同様に、作業するオブジェクトを設定します。recordSetVar では、レコードのコレクションで作成される変数の名前 (ここでは {! contacts }) を設定します。命名規則に従って、通常この変数には複数形のオブジェクト名が付けられます。

<apex:pageBlockTable> は、プラットフォームのスタイル設定が適用されたデータテーブルを生成する反復コンポーネントです。テーブルマークアップでの処理を次に示します。
  • <apex:pageBlockTable> の value 属性は、標準リストコントローラ {! contacts } で読み込まれた変数に設定されます。これは <apex:pageBlockTable> で操作するレコードのリストです。
  • そのリストの各レコードに対して 1 レコードずつ、<apex:pageBlockTable> はレコードを <apex:pageBlockTable> の var 属性で指定された変数に割り当てます。この場合、変数には ct が指定されます。
  • 各レコードに対して、<apex:pageBlockTable><apex:pageBlockTable> ボディ内の一連の <apex:column> コンポーネントで定義された行を使用して、テーブルに新しい行を作成します。<apex:column> コンポーネントは、現在のレコードを表す ct 変数を使用して、そのレコードの項目値を順に取得します。
  • ループの外側で、<apex:pageBlockTable><apex:column> コンポーネントの項目を使用して、各項目の表示ラベルを調べることで列ヘッダーを作成します。

これは非常に複雑で、最初は反復コンポーネントを理解することは難しいかもしれません。この時点でできることは、自分自身で作成してみることです。テーブルに表示する項目を選択します。<apex:pageBlockTable> および <apex:column> の別の属性を調べて、慣れるまで試してみてください。また、<apex:dataList><apex:repeat> など、その他いくつかの反復コンポーネントも使用してみてください。

リストへのリストビューの検索条件の追加

{! listViewOptions } を使用して、オブジェクトで使用可能なリストビュー検索条件のリストを取得します。{! filterId } を使用して、標準リストコントローラの結果に使用するリストビュー検索条件を設定します。

標準リストコントローラには、リストの表示を変更できる多数の機能があります。最も強力な機能の 1 つに、リストビュー検索条件があります。リストビュー検索条件は、コードを使用せずにクリックで宣言的に作成します。標準リストコントローラでは、ページで定義済みのリストビュー検索条件を使用できます。

  1. <apex:pageBlock> 全体を <apex:form> タグでラップします。標準リストコントローラのリストビュー検索条件を変更するには、新しい値をサーバに送信する必要があります。この送信を実行する一般的な方法は、<apex:form> コンポーネントで作成されたフォームを使用することです。
  2. <apex:pageBlock> タグで、次の属性を追加します。
    id="contacts_list"
    Ajax 効果 (これについては後ほど説明します) に使用できる「名前」が <apex:pageBlock> に付けられます。
  3. <apex:pageBlock> 開始タグの後、<apex:pageBlockTable> の上に、次のマークアップを追加します。
    Filter:
    <apex:selectList value="{! filterId }" size="1">
        <apex:selectOptions value="{! listViewOptions }"/>
        <apex:actionSupport event="onchange" reRender="contacts_list"/>
    </apex:selectList>
    ページの完全なコードは次のようになります。
    <apex:page standardController="Contact" recordSetVar="contacts">
        <apex:form>
            <apex:pageBlock title="Contacts List" id="contacts_list">
                Filter:
                <apex:selectList value="{! filterId }" size="1">
                    <apex:selectOptions value="{! listViewOptions }"/>
                    <apex:actionSupport event="onchange" reRender="contacts_list"/>
                </apex:selectList>
                <!-- Contacts List -->
                <apex:pageBlockTable value="{! contacts }" var="ct">
                    <apex:column value="{! ct.FirstName }"/>
                    <apex:column value="{! ct.LastName }"/>
                    <apex:column value="{! ct.Email }"/>
                    <apex:column value="{! ct.Account.Name }"/>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:form>
    </apex:page>
    新しい検索条件コントロールがリストの上に表示されます。リストビュー検索条件を含む取引先責任者リスト
  4. メニューから異なる検索条件を選択します。取引先責任者リストはどのように変化するでしょうか。

ここで作成した [検索条件] メニューから新しいオプションを選択すると、2 つの変化があります。まず、新しい検索条件を選択したときにレコードのリストが変更されます。(いくつかの異なるオプションの選択が必要な場合があります。標準の DE 組織のサンプルデータを使用している場合、複数のリストビューで同じレコードが表示されます)。

次に、あまり目立ちませんが、ページ全体は再読み込みされることなく、リストが更新されます。この「Ajax」効果は、<apex:actionSupport> コンポーネントの reRender="contacts_list" 属性で適用されます。コンポーネントと reRender の複合効果によって、reRender 属性で指定されたページの一部のみが更新されます。<apex:pageBlock>id="contacts_list" を追加しているため、アクションの完了時に、ページ全体が再読み込みされることなく <apex:pageBlock> のみが更新されます。

このページでのこの新機能の完全なライフサイクルは、次のようになります。
  • ページが読み込まれると、{! listViewOptions } 式からリストを取得することで、使用可能な検索条件のメニューが <apex:selectList> で作成されます。listViewOptions は、標準リストコントローラで提供されるプロパティです。
  • メニューから新しいオプションを選択すると、<apex:actionSupport> コンポーネントによって onchange イベントが起動されます。
  • onchange が起動すると、filterId プロパティに新しい項目を送信することで、新しく選択されたリストビューがページから戻され、<apex:selectList> に設定されます。
  • プロパティが更新されると、contacts 変数の新しい該当レコードのコレクションを含む、サーバからの新しい応答をページが受信します。
  • ただし、<apex:actionSupport> ではページの一部のみの表示が指定されているため、ページ全体が再読み込みされる代わりに、Ajax (非同期 JavaScript) を使用してページが更新されます。

正味の効果は、複雑で高度な動作をほんの数行のマークアップの追加で実現できることにあります。

ページネーションのリストへの追加

標準リストコントローラのページネーション機能を使用すると、ユーザは長いリストのレコードを 1 「ページ」ずつ表示できます。

これまで開発してきた機能は、Developer Edition 組織のサンプルデータとして提供されている短いリストのレコードでは快適に動作します。ただし、数百や数千、または数百万件のレコードがある実際の組織ではどうでしょうか。すべてのレコードを 1 ページに表示した場合は、うまく機能しません。

実際、デフォルトでは、標準リストコントローラは検索条件に一致する最初の 20 件 (存在する場合) のレコードのみを表示します。この 20 件以外のレコードにユーザがアクセスできるようにしたり、1 ページに 20 件を超えるレコードを表示したりするにはどうすればよいでしょうか。

答えはページネーションにあります。ページネーションは標準の Web アプリケーションユーザインターフェースです。長いリストのレコードを 1 「ページ」ずつ、通常は [次へ] および [前へ] リンクを使用して前後に移動できます。標準リストコントローラ、および進行状況インジケータやメニューなどのツールを使用してページにページネーションを追加し、ページあたりのレコード数を変更できます。

  1. 取引先責任者リスト <apex:pageBlockTable> の下に、次のマークアップを追加します。
    <!-- Pagination -->
    <table style="width: 100%"><tr>
        <td>
            <!-- Page X of Y -->
        </td>
        <td align="center">
            <!-- Previous page -->
            <!-- Next page -->
        </td>
        <td align="right">
            <!-- Records per page -->
        </td>
    </tr></table>
    追加する 3 つのページネーションコントロールを含めることができる HTML テーブルが作成されます。メモ実際のページでは、個別のスタイル設定によりセマンティックなマークアップが使用される場合もありますが、ここでは簡潔で追加ステップの不要なプレーン HTML を使用します。
  2. <!-- Page X of Y --> コメント行を次のマークアップで置き換えます。
    Page: <apex:outputText
        value=" {!PageNumber} of {! CEILING(ResultSize / PageSize) }"/>
    ユーザが表示しているページと残りのページ数を示す、進行状況インジケータがリストに追加されます。DE 組織で試行している場合は、「Page 1 of 1」 (1/1 ページ) と表示されます。
  3. <!-- Previous page --> および <!-- Next page --> コメント行を次のマークアップで置き換えます。
    <!-- Previous page -->
    <!-- active -->
    <apex:commandLink action="{! Previous }" value="« Previous"
         rendered="{! HasPrevious }"/>
    <!-- inactive (no earlier pages) -->
    <apex:outputText style="color: #ccc;" value="« Previous"
         rendered="{! NOT(HasPrevious) }"/>
    &nbsp;&nbsp;
    <!-- Next page -->
    <!-- active -->
    <apex:commandLink action="{! Next }" value="Next »"
         rendered="{! HasNext }"/>
    <!-- inactive (no more pages) -->
    <apex:outputText style="color: #ccc;" value="Next »"
         rendered="{! NOT(HasNext) }"/>
    このマークアップにより、ページに [前へ] および [次へ] リンクが追加されます。指定方向にさらに表示するレコードがある場合はリンクを有効にし、指定方向にそれ以上ページがない場合はリンクを無効にします。
  4. <!-- Records per page --> コメント行を次のマークアップで置き換えます。
    Records per page:
    <apex:selectList value="{! PageSize }" size="1">
        <apex:selectOption itemValue="5" itemLabel="5"/>
        <apex:selectOption itemValue="20" itemLabel="20"/>
        <apex:actionSupport event="onchange" reRender="contacts_list"/>
    </apex:selectList>
    このマークアップにより、ページあたりのレコード数を変更するメニューが追加されます。ここでは、1 ページにより少ないレコードを表示するオプションのみ追加されています。リストから「5」を選択し、リストとその他のコントロールがどのように変化するかを確認します。
標準リストコントローラで提供される多数の機能が含まれたリストページが表示されます。
ページネーションコントロールのある取引先責任者リスト

進行状況インジケータでは、何ページあるかを示すために PageNumberResultSizePageSize の 3 つのプロパティが使用されています。最後の 2 つは、最も近い整数に四捨五入する数式で使用されます。これにより、インジケータに「Page 2 of 1.6」 (2/1.6 ページ) などの不適切な値が表示されることを防ぎます。

ページネーションコントロールの <apex:commmandLink> コンポーネントは、標準リストコントローラ Previous および Next で提供される 2 つのアクションメソッドを参照します。その結果、Previous または Next アクションを実行するリンクが表示されます。

では、{! HasPrevious } などの式が含まれる rendered 属性は何を意味するのでしょうか。Visualforce はこの属性によって、コンポーネントを条件付きで (Boolean 式の結果に応じて) 表示できるようにします。ここでは、ページマークアップは標準リストコントローラ HasPrevious および HasNext で提供される Boolean プロパティを参照しています。これらのコントローラは、指定方向にさらにレコードがあるかどうかを示します。rendered 属性でこの式を使用することで、そのコンポーネントの結果をページに表示または非表示にすることができます。これにより、ページを最初に読み込んだときは [前へ] リンクがグレー表示になり、[次へ] リンクをクリックして先に進むと有効になります。

ページあたりのレコード数選択メニューでは、以前に使用した <apex:selectList> を使用しますが、メニューの値を取得するコントローラメソッドをコールする代わりに、目的の値の <apex:selectOption> 要素を使用します。ここでも、<apex:actionSupport> タグは選択値が変更された場合にメニューのアクションを実行し、reRender="contacts_list" を使用して <apex:pageBlock> のみを更新します。ここで異なる点は、<apex:selectList> で標準リストコントローラの PageSize プロパティを設定していることです。

もうひとこと...

標準リストコントローラには Web アプリケーションで一般的な多数の機能があり、ここで紹介している機能はほんの一部にすぎません。

たとえば、1 ページごとに前後に移動する Previous および Next アクションに加えて、レコードのリストの先頭または最後に移動する First および Last アクションもあります。

マークアップで操作する標準リストコントローラは、StandardSetController Apex クラスに基づいています。このクラスの詳細およびそのすべての機能は、『Lightning Platform Apex コード開発者ガイド』に記載されています。

ここで作成した例では、並び替えの問題があります。通常はリストのデフォルトの並び替え順を設定し、並び替え順をその場で変更できる列ヘッダーを含めることが望まれます。実際には、Visualforce 単独で並び替え順を変更することはできません。並び替えとクリック可能な列ヘッダーをサポートするために必要な追加の Visualforce マークアップと Apex コードの量はそれほど多くありませんが、カスタムコードが必要になります。その開始点については、その他のリソースを参照してください。