Visualforceページとカスタムコンポーネントによるモーダルダイアログの実装

September 5, 2011 Appirio

VBアプリケーションなどのローカルアプリケーションでは、モーダルダイアログを用いてエラーメッセージを表示したり、モーダルウインドウで選択した情報をメインウインドウに反映したりといったユーザーインターフェイスが度々用いられます。

これらをWebアプリケーションで実現しようとした場合、window.showModalDialogメソッドを使用する方法もありますが、HTML、CSS、Javascriptを組み合わせたモーダルダイアログを用いる方法が非常に有効だと考えます。(ちなみに、window.showModalDialogは、Chromeだとダイアログがモーダルになりません)

そこで今回は、Force.com上でjQueryUIを用いたモーダルダイアログをカスタムコンポーネントとして実装する方法をご紹介します。ダイアログとコントローラクラスをカスタムコンポーネントとして共通化し、メインとなる画面のロジックとダイアログ内のロジックを切り分け、汎用的に使用できるようにしたいと思います。

サンプルの概要は下記の通りです。

ダイアログを用いた掛け算

概要:メインとなる画面に被乗数を入力し、モーダルダイアログに乗数を入力して計算を行い、計算結果をメインの画面に戻す

今回使用するファイルの一覧

  • CalcDTO.cls – ダイアログの呼び出し元で入力された値と、ダイアログの計算結果を受け渡しするためのDTOクラス
  • Parent_Page.page – ダイアログの呼び出し元となる画面のVisualforceページ
  • Parent_Ctrl.cls – ダイアログの呼び出し元となる画面のコントローラクラス
  • Dialog_Comp.component - ダイアログのカスタムコンポーネント
  • Dialog_Ctrl.cls - ダイアログのカスタムコンポーネントで使用するコントローラクラス

処理の流れ

  1. 入力項目に掛けられる値(被乗数)を入力
  2. Visualforceページ内の[GO]ボタンのアクションとして、コントローラクラスのメソッドを呼び出す
  3. モーダルダイアログの表示(ダイアログコンポーネントエリアを再描画)
  4. ダイアログコンポーネント内の入力項目に掛ける値(乗数)を入力
  5. ダイアログコンポーネント内の[計算]ボタンのアクションとして、コントローラクラスのメソッドを呼び出す
  6. 「OK」ボタンでダイアログのクローズとメインページの復帰(計算結果エリアを再描画)

Visualforceページとカスタムコンポーネント間の値の受け渡しや、actionStatus、actionFunctionを相互に呼び出す方法を確認しながら、掛け算ダイアログのサンプルを作成していきたいと思います。

jQuery UIの登録
まず、jQueryをForce.com 上に静的リソースとして登録します。jQuery UIは、下記URLからダウンロード可能です。

http://jqueryui.com/download

ダウンロードしたファイル(jquery-ui-1.8.16.custom.zip)を展開し、jsフォルダ、cssフォルダを確認してください。さらに、コントローラクラスのメソッド呼び出し中にローディングアイコンを表示したいので、フリー素材などから用意して”loading.gif”という名前でimagesフォルダ内に格納してください。

  • js
  • css
  • images

の3フォルダをzip 形式でアーカイブし、静的リソースに "jQueryUI" という名前で登録します。

メインページの作成
今回の掛け算ダイアログの呼び出し元として、被乗数を入力し、ダイアログでの計算結果を表示する画面をForce.com 上に作成します。まず最初に、ダイアログの呼び出し元となるコントローラクラスとダイアログのカスタムコンポーネントで使用するコントローラクラスの間で入力値(被乗数)と計算結果を受け渡しするため、DTOクラスを作成します。

CalcDTO.cls

 

public with sharing class CalcDTO {

  /** 被乗数 */
  public Integer param { get; set; }

  /** 計算結果 */
  public Integer answer { get; set; }

  public CalcDTO() {
    this.param = 0;
    this.answer= 0;
  }

}

 

メイン画面の入力値(被乗数)を”param”、ダイアログでの計算結果を”answer”として定義し、初期化します。

Parent_Ctrl.cls

 

public with sharing class Parent_Ctrl {

  // 受け渡し用Class 
  public CalcDTO calcDTO { get; set; }

  public Parent_Ctrl() {
    // 初期化
    this.calcDTO = new CalcDTO();
  }

  /**
  * [GO]ボタン
  */
  public PageReference reloadParam() {
    return null;
  }

  /**
  * 画面復帰時に実行
  */
  public PageReference refreshParent() {
    return null;
  }

}

 

Parent_Page.page

 

<apex:page controller="Parent_Ctrl">
  <apex:includeScript value="{!$Resource.jQueryUI}/js/jquery-1.6.2.min.js"/>
  <apex:includeScript value="{!$Resource.jQueryUI}/js/jquery-ui-1.8.16.custom.min.js"/>
  <apex:stylesheet value="{!$Resource.jQueryUI}/css/ui-lightness/jquery-ui-1.8.16.custom.css"/>
  <!-- 【メインページ】 -->
  <apex:form>
    <apex:pageBlock>
      <apex:pageBlockSection>
        <apex:panelGroup >
          <apex:inputText value="{!calcDTO.param}" />
          <apex:commandButton action="{!reloadParam}" value="GO" rerender="dialogPanel" status="loadComponent" onClick="jQuery('#dialog-modal').dialog('open');"/>
          <!-- ロード中ステータス表示  -->
          <apex:actionFunction name="refreshParent" action="{!refreshParent}" rerender="refreshParent" status="loadParent" />
          <apex:actionStatus id="loadParent">
            <apex:facet name="start">
              <img src="{!$Resource.CommonStyle}/images/loading.gif" width="24" height="24"/>
            </apex:facet>
          </apex:actionStatus>
        </apex:panelGroup>
        <apex:outputText value="A: {!calcDTO.answer}" id="refreshParent"/>
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>

  <!-- 【モーダルダイアログ】 -->
  <div id="dialog-modal" title="ダイアログ">
    <apex:outputPanel id="dialogPanel">
      <c:Dialog_Comp calcDTO="{!calcDTO}"/>
    </apex:outputPanel>
  </div>

  <!-- 【JAVASCRIPT】 -->
  <script language="javascript" type="text/javascript">
    jQuery.noConflict();
    jQuery(function() {
      //ダイアログを表示
      jQuery( "#dialog-modal" ).dialog({
        modal: true,
        autoOpen: false,
        width: 800,
        buttons: {
          "確定": function() {
            jQuery( this ).dialog( "close" );
            // actionfunctionの呼び出し
            refreshParent();
          },
          "キャンセル": function() {
            jQuery( this ).dialog( "close" );
          }
        }
      });
    });
  </script>  
</apex:page>

 

Parent_Page.pageでは、掛け算の被乗数を入力し、[GO]ボタンでc:Dialog_Compを含めたエリアを再描画し、被乗数をパラメータとしたカスタムコンポーネントを呼び出す形になります。
また、[GO]ボタンのonClickで、ダイアログが呼び出されると同時に、コンポーネント内のactionStatus(loadComponent)を呼び出し、ローディングアイコンを表示するようにしています。
※Force.com上では、「$」が使用済みのため、衝突を回避するために”noConfrict”を実行しておきます。

ダイアログの作成
被乗数を受取り、ダイアログ内に入力された乗数との計算結果を表示するカスタムコンポーネントを Force.com 上に作成します。

Dialog_Ctrl.cls

 

public with sharing class Dialog_Ctrl {

    // ダイアログで入力された値
    public Integer times { get; set; }

    // 受け渡し用Class
    public CalcDTO calcDTO { get; set; }

    public Dialog_Ctrl(){
        // ダイアログ内の入力値を初期化
        this.times = 0;
    }

    /**
    * [計算]ボタンで計算を実行
    */
    public PageReference culc(){
        this.calcDTO.answer = this.calcDTO.param * this.times;
        return null;
    }
}

 

Dialog_Comp.component

 

<apex:component controller="Dialog_Ctrl" id="comp">
	<apex:attribute name="calcDTO" type="CalcDTO" assignTo="{!calcDTO}" description="key"/>
	<apex:form id="f_comp">
		<!-- 表示エリア  -->
		<apex:pageBlock id="b_comp">
			<apex:pageBlockSection>
				<apex:panelGroup >
					<apex:outputText value="{!calcDTO.param}" />×
					<apex:inputText value="{!times}" />=
					<apex:outputText value="{!calcDTO.answer}" />
					<apex:commandButton action="{!culc}" value="計算" rerender="b_comp"/>
				</apex:panelGroup>
				<!-- ロード中ステータス表示  -->
				<apex:actionStatus id="loadComponent">
					<apex:facet name="start">
						<img src="{!$Resource.CommonStyle}/images/loading.gif" width="24" height="24"/>
					</apex:facet>
				</apex:actionStatus>
			</apex:pageBlockSection>
		</apex:pageBlock>
	</apex:form>
</apex:component>

 

Dialog_Comp.componentでは、掛け算の乗数を入力し、[計算]ボタンでコントローラクラスのメソッド(culc)が呼び出されます。
culcメソッドでは、ダイアログに入力された乗数とパラメータとして受け取った被乗数を使用して掛け算を実行し、計算結果をCalcDTOの”answer”にセットします。同時に、ダイアログ内のPageBlock(b_comp)を再描画し、計算結果を表示します。

Parent_Page.pageで作成したダイアログの[確定]ボタンでダイアログを閉じると同時に、JavascriptのrefreshParent()が呼び出されます。Javascriptから、Visualfoceページ内のactionFunctionで指定された名称(name="refreshParent")をJavascript関数として呼び出すことで、コントローラクラスのメソッドにアクセスすることができます。
refreshParentメソッドを実行すると同時に、メインページ内のStatus(loadParent)を呼び出し、ローディングアイコンを表示するようにしています。
最後に、計算結果エリアを再描画して、処理は終了です。

Force.comで標準機能として提供されている検索ポップアップでは実現できない複雑な検索が必要になったときなどにもダイアログは非常に有効かと思います。是非ご活用ください。

 

Posted by Yoshida Tokuji (Appirio Japan)

 

 

 

戻る
Java がサポートされたクラウド環境 Heroku で Play!Scala を試す
Java がサポートされたクラウド環境 Heroku で Play!Scala を試す

先日Herokuで「Heroku for Java」の発表がされました。http://blog.heroku.com/archives/2011/8/25/java/ Herokuはスケールアウト可能なクラウド上の...

次へ
Dreamforce ’11 Mark Benioff 基調講演 二日目
Dreamforce ’11 Mark Benioff 基調講演 二日目

Dreamforce二日目の基調講演では、マーク・ベニオフから開発者向けのアプリケーションプラットフォームの発表がありました。 一日目に語られた「ソーシャルエンタープライズへの三つのステップ」と、開発プラットフォー...

アピリオまでお気軽にお問合せください

ご質問はこちら