この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

ウィザードの作成

ここまで Visualforce マークアップとコントローラの重要な機能について説明してきましたが、この最後の例では、こうした機能を一緒に使用して 3 ステップから成るカスタムウィザードを作成する方法を説明します。このウィザードでは、次のようにユーザが商談と同時に、関連する取引先責任者、取引先、および取引先責任者のロールを作成できます。
  • ステップ 1: 取引先と取引先責任者に関連する情報を収集する
  • ステップ 2: 商談に関連する情報を収集する
  • ステップ 3: 作成されるレコードを表示し、ユーザが保存またはキャンセルできるようにする
このウィザードを実装するには、ウィザードの 3 つのステップのそれぞれに対応する 3 ページと、各ページ間のナビゲーションの設定とユーザが入力したデータの追跡を行う 1 つのカスタムコントローラを定義します。

複数の Visualforce ページにまたがって使用されるデータは、最初のページでデータを使用しない場合でも、最初のページ内で定義する必要があります。たとえば、項目が 3 ステッププロセスの 2 ページ目と 3 ページ目で必要な場合、1 ページ目にもその項目が含まれている必要があります。項目の rendered 属性を false に設定することで、この項目をユーザに非表示にすることもできます。

重要

これらの各コンポーネントのコードは、下記のセクションに含まれていますが、3 つのページはそれぞれコントローラを参照し、コントローラは 3 つのページをそれぞれ参照するため、まずその最適な作成手順を理解する必要があります。やっかいなことは、ページがないとコントローラを作成できませんが、コントローラでページを参照するにはページが存在している必要があるということです。

この問題を解決するには、最初に完全に空のページを定義し、次にコントローラを作成してから、マークアップをページに追加します。したがって、ウィザードページとコントローラを作成する最適な手順は次のようになります。
  1. 1 ページ目の URL の https://Salesforce_instance/apex/opptyStep1 に移動し、[Create Page opptyStep1 (ページ opptyStep1 を作成)] をクリックします。
  2. ウィザードの他のページである opptyStep2opptyStep3 についても、上記のステップを繰り返します。
  3. newOpportunityController コントローラを属性としていずれかのページ上の <apex:page> タグに追加し (<apex:page controller="newOpportunityController"> など)、次に [Apex controller newOpportunityController (Apex コントローラ newOpportunityController を作成)] をクリックして、コントローラを作成します。すべてのコントローラコードを貼り付けて、[Save (保存)] をクリックします。
  4. ここで、作成した 3 つのページのエディタに戻り、それらのコードをコピーします。これでウィザードは期待どおりに機能します。

空のページを作成することはできますが、その逆のことはできません。ページがコントローラを参照するためには、そのコントローラのすべてのメソッドとプロパティが設定されている必要があります。

メモ

商談ウィザードコントローラ

次の Apex クラスは、新規顧客商談ウィザードの 3 つのページすべてのコントローラです。

1public class newOpportunityController {
2
3   // These four member variables maintain the state of the wizard.
4   // When users enter data into the wizard, their input is stored
5   // in these variables. 
6   Account account;
7   Contact contact;
8   Opportunity opportunity;
9   OpportunityContactRole role;
10
11
12   // The next four methods return one of each of the four member
13   // variables. If this is the first time the method is called,
14   // it creates an empty record for the variable.
15   public Account getAccount() {
16      if(account == null) account = new Account();
17      return account;
18   }
19
20   public Contact getContact() {
21      if(contact == null) contact = new Contact();
22      return contact;
23   }
24
25   public Opportunity getOpportunity() {
26      if(opportunity == null) opportunity = new Opportunity();
27      return opportunity;
28   }
29
30   public OpportunityContactRole getRole() {
31      if(role == null) role = new OpportunityContactRole();
32      return role;
33   }
34
35
36   // The next three methods control navigation through
37   // the wizard. Each returns a PageReference for one of the three pages
38   // in the wizard. Note that the redirect attribute does not need to
39   // be set on the PageReference because the URL does not need to change
40   // when users move from page to page.
41   public PageReference step1() {
42      return Page.opptyStep1;
43   }
44
45   public PageReference step2() {
46      return Page.opptyStep2;
47   }
48
49   public PageReference step3() {
50      return Page.opptyStep3;
51   }
52
53
54   // This method cancels the wizard, and returns the user to the 
55   // Opportunities tab
56    public PageReference cancel() {
57      PageReference opportunityPage = new PageReference('/006');
58      opportunityPage.setRedirect(true);
59      return opportunityPage; 
60    }
61
62   // This method performs the final save for all four objects, and
63   // then navigates the user to the detail page for the new
64   // opportunity.
65   public PageReference save() {
66
67      // Create the account. Before inserting, copy the contact's
68      // phone number into the account phone number field.
69      account.phone = contact.phone;
70      insert account;
71
72      // Create the contact. Before inserting, use the id field
73      // that's created once the account is inserted to create
74      // the relationship between the contact and the account.
75      contact.accountId = account.id;
76      insert contact;
77
78      // Create the opportunity. Before inserting, create 
79      // another relationship with the account.
80      opportunity.accountId = account.id;
81      insert opportunity;
82
83      // Create the junction contact role between the opportunity
84      // and the contact.
85      role.opportunityId = opportunity.id;
86      role.contactId = contact.id;
87      insert role;
88
89      // Finally, send the user to the detail page for 
90      // the new opportunity.
91
92
93      PageReference opptyPage = new ApexPages.StandardController(opportunity).view();
94      opptyPage.setRedirect(true);
95
96      return opptyPage;
97   }
98
99}

商談ウィザードのステップ 1

次のコードは、ウィザードの 1 ページ目 (opptyStep1) を定義します。このページでは、関連付けられた取引先責任者と取引先に関するデータをユーザから収集します。

1<apex:page controller="newOpportunityController" tabStyle="Opportunity">
2  <script>
3  function confirmCancel() {
4      var isCancel = confirm("Are you sure you wish to cancel?");
5      if (isCancel) return true;
6  
7     return false;
8  }  
9  </script>
10  <apex:sectionHeader title="New Customer Opportunity" subtitle="Step 1 of 3"/>
11    <apex:form>
12      <apex:pageBlock title="Customer Information" mode="edit">
13
14        <!-- The pageBlockButtons tag defines the buttons that appear at the top
15             and bottom of the pageBlock. Like a facet, it can appear anywhere in
16             a pageBlock, but always defines the button areas.-->
17        <!-- The Next button contained in this pageBlockButtons area
18             calls the step2 controller method, which returns a pageReference to
19             the next step of the wizard. -->
20        <apex:pageBlockButtons>
21          <apex:commandButton action="{!step2}" value="Next"/>
22          <apex:commandButton action="{!cancel}" value="Cancel" 
23                              onclick="return confirmCancel()" immediate="true"/>
24        </apex:pageBlockButtons>
25      <apex:pageBlockSection title="Account Information">
26
27        <!-- Within a pageBlockSection, inputFields always display with their
28             corresponding output label. -->
29        <apex:inputField id="accountName" value="{!account.name}"/>
30        <apex:inputField id="accountSite" value="{!account.site}"/>
31      </apex:pageBlockSection>
32      <apex:pageBlockSection title="Contact Information">
33        <apex:inputField id="contactFirstName" value="{!contact.firstName}"/>
34        <apex:inputField id="contactLastName" value="{!contact.lastName}"/>
35        <apex:inputField id="contactPhone" value="{!contact.phone}"/>
36      </apex:pageBlockSection>
37    </apex:pageBlock>
38  </apex:form>
39</apex:page>
ウィザードの 1 ページ目のマークアップについては、次の点に留意してください。
  • <apex:pageBlock> タグは、必要に応じて <apex:pageBlockButtons> 子要素を取り込み、コンポーネントのヘッダーとフッターに表示されるボタンを制御できます。<apex:pageBlock> の本文に表示される <apex:pageBlockButtons> タグの順序は重要ではありません。ウィザードのこのページでは、<apex:pageBlockButtons> タグに、ページブロック領域のフッターに表示される [次へ] ボタンが含まれます。
  • ウィザードは、[キャンセル] ボタンがクリックされると JavaScript コードを利用してダイアログボックスを表示し、終了するかどうかをユーザに確認します。この例では、簡略化のためにマークアップに直接 JavaScript を含めていますが、実際には JavaScript コードを静的リソースに配置してそのリソースを代わりに参照することをお勧めします。
  • ウィザードのこのページでは、[次へ] ボタンがコントローラの step2 メソッドをコールし、そのメソッドが PageReference をウィザードの次のステップに返します。
    1<apex:pageBlockButtons>
    2    <apex:commandButton action="{!step2}" value="Next"/>
    3</apex:pageBlockButtons>

    コマンドボタンはフォームに表示する必要があります。これは、フォームコンポーネント自体が、新しい PageReference に基づいてページ表示を更新するためです。

  • <apex:pageBlockSection> タグは、データのセットを表示用に整理します。テーブルと同様に、<apex:pageBlockSection> は 1 つ以上の列で構成され、各列は 2 つのセル (1 つは項目の表示ラベル、1 つは値) に展開されます。<apex:pageBlockSection> タグの本文に含まれる各コンポーネントは、列数に達するまで、行内の次のセルに配置されます。列数に達したら、その次のコンポーネントは次の行の最初のセルに配置されます。

    <apex:inputField> などの一部のコンポーネントは、自動的にページブロックセクション列の両方のセルに一度に展開され、項目の表示ラベルと値の両方に入力されます。たとえば、このページの [取引先責任者情報] 領域では、[名] 項目が最初の列、[姓] 項目が 2 番目の列に入り、[電話] 項目が次の行の最初の列に折り返します。

    1<apex:pageBlockSection title="Contact Information">
    2  <apex:inputField id="contactFirstName" value="{!contact.firstName}"/>
    3  <apex:inputField id="contactLastName" value="{!contact.lastName}"/>
    4  <apex:inputField id="contactPhone" value="{!contact.phone}"/>
    5</apex:pageBlockSection>
  • 前のコードの抜粋に含まれる最初の <apex:inputField> タグの value 属性は、コントローラの getContact メソッドから返された取引先責任者レコードの firstName 項目にユーザの入力を割り当てます。
ページは次のようになります。
新規顧客商談ウィザードのステップ 1 新規顧客商談ウィザードのステップ 1。2 つのセクション [取引先情報] と [取引先責任者情報] が表示されます。

商談ウィザードのステップ 2

次のコードは、ウィザードの 2 ページ目 (opptyStep2) を定義します。このページでは、商談に関するデータをユーザから収集します。

1<apex:page controller="newOpportunityController" tabStyle="Opportunity">
2  <script>
3  function confirmCancel() {
4      var isCancel = confirm("Are you sure you wish to cancel?");
5      if (isCancel) return true;
6  
7     return false;
8  }  
9  </script>
10  <apex:sectionHeader title="New Customer Opportunity" subtitle="Step 2 of 3"/>
11  <apex:form>
12    <apex:pageBlock title="Opportunity Information" mode="edit">
13      <apex:pageBlockButtons>
14        <apex:commandButton action="{!step1}" value="Previous"/>
15        <apex:commandButton action="{!step3}" value="Next"/>
16        <apex:commandButton action="{!cancel}" value="Cancel" 
17                            onclick="return confirmCancel()" immediate="true"/>
18      </apex:pageBlockButtons>
19      <apex:pageBlockSection title="Opportunity Information">
20        <apex:inputField id="opportunityName" value="{!opportunity.name}"/>
21        <apex:inputField id="opportunityAmount" value="{!opportunity.amount}"/>
22        <apex:inputField id="opportunityCloseDate" value="{!opportunity.closeDate}"/>
23        <apex:inputField id="opportunityStageName" value="{!opportunity.stageName}"/>
24        <apex:inputField id="contactRole" value="{!role.role}"/>
25      </apex:pageBlockSection>
26    </apex:pageBlock>
27  </apex:form>
28</apex:page>

フォームに [完了予定日][フェーズ]、および [取引先責任者の役割] 項目を配置するマークアップは、他の項目と同じですが、<apex:inputField> タグが各項目のデータ型を調べて表示方法を決定します。たとえば、[完了予定日] テキストボックスをクリックするとカレンダーが表示され、そこからユーザが日付を選択できます。

ページは次のようになります。
新規顧客商談ウィザードのステップ 2 新規顧客商談ウィザードのステップ 2。[商談情報] というセクションが表示されます。

商談ウィザードのステップ 3

最後のコードブロックは、ウィザードの 3 ページ目 (opptyStep3) を定義します。このページでは、すべての入力データが表示されます。ユーザは、操作を保存するか、前のステップに戻るかを決定できます。

1<apex:page controller="newOpportunityController" tabStyle="Opportunity">
2  <script>
3  function confirmCancel() {
4      var isCancel = confirm("Are you sure you wish to cancel?");
5      if (isCancel) return true;
6  
7     return false;
8  }  
9  </script>
10  <apex:sectionHeader title="New Customer Opportunity" subtitle="Step 3 of 3"/>
11  <apex:form>
12    <apex:pageBlock title="Confirmation">
13      <apex:pageBlockButtons>
14          <apex:commandButton action="{!step2}" value="Previous"/>
15          <apex:commandButton action="{!save}" value="Save"/>
16          <apex:commandButton action="{!cancel}" value="Cancel" 
17                              onclick="return confirmCancel()" immediate="true"/>
18      </apex:pageBlockButtons>
19      <apex:pageBlockSection title="Account Information">
20        <apex:outputField value="{!account.name}"/>
21        <apex:outputField value="{!account.site}"/>
22      </apex:pageBlockSection>
23      <apex:pageBlockSection title="Contact Information">
24        <apex:outputField value="{!contact.firstName}"/>
25        <apex:outputField value="{!contact.lastName}"/>
26        <apex:outputField value="{!contact.phone}"/>
27        <apex:outputField value="{!role.role}"/>
28      </apex:pageBlockSection>
29      <apex:pageBlockSection title="Opportunity Information">
30        <apex:outputField value="{!opportunity.name}"/>
31        <apex:outputField value="{!opportunity.amount}"/>
32        <apex:outputField value="{!opportunity.closeDate}"/>
33      </apex:pageBlockSection>
34    </apex:pageBlock>
35  </apex:form>
36</apex:page>

ウィザードの 3 ページ目では、テキストを <apex:outputField> タグでページに書き込むだけです。

最後のページは次のようになります。
新規顧客商談ウィザードのステップ 3 新規顧客商談ウィザードのステップ 3。入力されたセクション [取引先情報]、[取引先責任者情報]、および [商談情報] が確認のために表示されます。