Appirio's Tech Blog

2011年7月13日水曜日

Visualforceページ上での引数付きメソッド呼び出し

通常、Visualforceページに値を埋め込む場合、Getterメソッドを使用しますが引数を与えて呼び出すことはできません。しかし、カスタムコンポーネントを利用することで、Visualforce上でのメソッド呼び出しで擬似的に引数を与えることができます。

このエントリーでは、Visualforceページ上で引数を与えてメソッドを呼び出す方法を紹介します。

次のようなサンプルを考えてみます。
  • データとして「色-値」のようにハイフン区切りで色と値をセットで持つ文字列を用意する。
  • サンプルカスタムコントローラが上記文字列の配列を保持する。
  • サンプルメソッドは「色-値」形式の文字列を引数に取り、「<span style="color:色;">値</span>」形式の文字列を返す。
  • サンプルVisualforceページではサンプルコントローラの持つ配列の各要素を引数に、繰り返しサンプルメソッドを呼び出す。
今回使用するファイルの一覧は次の通りです。
  • ColoredString.cls-サンプルメソッドの実装クラスです。
  • BindSampleController.cls-サンプルカスタムコントローラです。
  • BindSample.page-今回作成するカスタムコンポーネントを使用するVisualforceページのサンプルです。
  • bind.component-今回作成するカスタムコンポーネント定義です。
  • BindComponentController.cls-上記カスタムコンポーネントで使用するカスタムコントローラです。
  • Executor.cls-カスタムコンポーネントで利用するメソッドを汎用化するためのインタフェースです。
では実際のコードを見ていきましょう。サンプルメソッドの実装クラスは次のようになります。

ファイル名:ColoredString.cls
public class ColoredString implements Executor {

 public Object execute(Object param){
  //色、値の順で配列に格納する
  String[] colorAndValue = ((String)param).split('-');
  //HTMLのspanタグに色と値を埋め込んだ文字列を返す
  return String.format('<span style="color:{0};">{1}</span>', colorAndValue);
 }

}
引数で受け取った「色-値」形式の文字列をハイフンで分割してHTML文字列に適用して返しています。
カスタムコンポーネントで利用するメソッドをここで実装しています。

サンプルコントローラは次のようになります。

ファイル名:BindSampleController.cls
public class BindSampleController {
 public Executor colorer {get;set;}

 public String[] colorAndValues {
  //「色-値」の配列を返すGetterメソッド
  get {
   return new String[]{'#FF0000-foo', '#00FF00-bar','#0000FF-baz'};
  }
 }
 
 public BindSampleController(){
  colorer = new ColoredString();
 }
}
コンストラクタでプロパティcolorerにサンプルメソッドの実装クラスをセットしています。
プロパティcolorAndValuesは「色-値」形式の文字列を配列として持っています。

Visualforceページのサンプルは次です。

ファイル名:BindSample.page
<apex:page controller="BindSampleController">

 <!-- 「色-値」形式の文字列を繰り返し処理する -->
 <apex:repeat value="{!colorAndValues}" var="myParam">

  <!-- カスタムコンポーネントによりサンプルメソッドを呼び出す -->
  <c:bind var="result" param="{!myParam}" executor="{!colorer}">

   <!-- メソッドの戻り値がセットされた変数resultを出力する -->
   <apex:outputText value="{!result}" escape="false"/>

  </c:bind><br/>
 </apex:repeat>

</apex:page>
c:bindは今回作成するカスタムコンポーネントです。
サンプルメソッドの実装クラスを属性executorに、メソッドに与える引数を属性paramに指定しています。
属性varはメソッドの戻り値をセットする変数名を指定します。

ではカスタムコンポーネントのコードを見ていきましょう。

ファイル名:bind.component
<apex:component controller="BindComponentController">
 <apex:attribute name="var" required="true" type="Object" description="The variable to represent a value of map"/>
 <apex:attribute name="param" required="true" type="Object" assignTo="{!param}" description="parameter"/>
 <apex:attribute name="executor" required="true" type="Executor"  assignTo="{!executor}" description="executor"/>

 <apex:outputText value="{!XXresultXX}" rendered="{!valOnly}"/>
 
 <apex:componentBody rendered="{!NOT(valOnly)}">
  <apex:variable var="{!var}" value="{!XXresultXX}"/>
 </apex:componentBody> 
</apex:component>
属性に指定された値はカスタムコンポーネントのコントローラにセットされます。属性の役割については前述の通りです。

bind.componentの6行目ではc:bindに子要素が与えられない場合の出力を行なっています。「<c:bind param="{!...}" executor="{...}"/>」のように属性varが指定されない場合、メソッドの実行結果を単に出力します。

8-10行目では子要素が与えられた場合の出力を行なっています。「<c:bind var"{!result}" =param="{!...}" executor="{...}">{!result}</c:bind>」のように属性varが指定された場合、c:bindの子要素で任意のVisualforceコンポーネントに値を埋め込むことができます。(サンプルでは子要素が与えられた場合のみ記載しています)。

カスタムコンポーネントのコントローラは次のようになります。

ファイル名:BindComponentController.cls
public class BindComponentController {
 public Object var {
  get;
  set{
   //属性varの有無による子要素の表示制御
   valOnly = true;
   var = value;
  }
 }
 public Object param {get; set;}
 public Executor executor {get; set;}
 public Boolean valOnly {get; set;}
 
 public BindComponentController(){
  valOnly = false;
 }
 
 public Object getXXResultXX(){
  return executor.execute(param);
 }
}
プロパティvarのsetterメソッドでは前述の子要素の表示制御の処理を行っています。
c:bindに属性varが指定されないときは子要素の表示を行わないようにしています。

BindComponentController.clsの19行目getXXResultXXメソッドでExecutorのメソッドを実行しています。getXXResultXXはおかしなメソッド名ですね。カスタムコンポーネント定義内のメソッドの結果を使用するプロパティ名(XXResultXX)とc:bindのvar属性にセットされた値が同一ときに挙動がおかしくなるので、名前の重複を防ぐためにこのような名前にしています。

Executorインタフェースの説明はもう必要ありませんね。

ファイル名:Executor.cls
public interface Executor {
 Object execute(Object param);
}
以上で、引数付きのメソッド呼び出しがVisualforce上で行えるようになります。

最後に、c:bindが呼ばれるにつれBindComponentControllerのコンストラクタの呼び出しも増えて行くので過剰な利用に注意してください。

Posted by Satake Chikara (Appirio Japan)

0 コメント:

コメントを投稿

 
2006-2011 Appirio Inc. All rights reserved.
アピリオ | リソースセンター(英語) | お問い合わせ先 | 採用情報 | プライバシーポリシー(英語)