いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Tapestry奮闘記-0026 (PropertySelectionコンポーネント)

PropertySelectionコンポーネントもSelect,Optionと同じようにドロップダウンリストを
レンダリングします。違いは、こちらは内部でorg.apache.tapestry.form.IPropertySelectionModelを
持ち、それを利用してレンダリングを行います。

IPropertySelectionModelインターフェースには、StringPropertySelectionModelなどの実装クラスが
既に用意されているのですが、実際に案件などで使用する場合は、単純に文字列でやりとりするより
独自に作成したドメインオブジェクトなどを利用して表示するほうが多いでしょう。
(たとえば、DBの値を元にドロップダウンを作成したりなど)

今回は、適当なデータクラスを作成し、それ用のIPropertySelectionModelの実装を作成します。
実装クラスの作成自体はそんなに難しくありません。

[HTMLテンプレート]

                    <!--
                    
                        PropertySelectionコンポーネントを使用する.
                        (PropertySelectionコンポーネントを使用。)

                    -->
                    <br/>
                    <hr/>
                    <div id="select_component_001" align="center">
                        <b>
                            PropertySelectionコンポーネントを使用<br/>
                            <br/>
                            PropertySelectionコンポーネントを使用。<br/>
                            <br/>
                        </b>
                        <br/>
                        出力:
                        <br/>
                        <form jwcid="selectSample002@Form" listener="listener:selectSample002FormSubmit">
                            <select jwcid="select002@PropertySelection" model="ognl:select002PropertySelectionModel" value="ognl:select002ModelValue">
                                <option value="1">HOGE</option>
                                <option value="2">HEHE</option>
                            </select>
                            <input type="submit" value="実行"/>
                        </form>
                        <br/>
                        <br/>
                    </div>
                    <hr/>
                    <br/>

データクラスとして、strutsにあるLabelValueBeanみたいなのを作成しました。
[データクラス]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.tapestry;

import org.apache.commons.lang.builder.*;

/**
 * ラベルと値を持つデータクラス.<br/>
 *
 * @author gsf_zero1
 *
 */
public class LabelValueBean{

    /** ラベル */
    private String label;

    /** 値 */
    private Object value;

    /**
     * コンストラクタ.<br/>
     *
     */
    public LabelValueBean(){
        this.label = null;
        this.value = null;
    }

    /**
     * コンストラクタ.<br/>
     *
     * @param label ラベル
     * @param value 値
     *
     */
    public LabelValueBean(String label, Object value){
        this.label = label;
        this.value = value;
    }
    
    /**
     * Get label.
     *
     * @return label as String.
     */
    public String getLabel(){
        return this.label;
    }
    
    /**
     * Set label.
     *
     * @param label the value to set.
     */
    public void setLabel(String label){
        this.label = label;
    }
    
    /**
     * Get value.
     *
     * @return value as Object.
     */
    public Object getValue(){
        return this.value;
    }
    
    /**
     * Set value.
     *
     * @param value the value to set.
     */
    public void setValue(Object value){
        this.value = value;
    }

    /**
     * オブジェクトの文字列表現を返す.<br/>
     *
     * @return 文字列表現
     *
     */
    @Override
    public String toString(){
        return new ReflectionToStringBuilder(this).toString();
    }
}

次に、これを利用するIPropertySelectionModelの実装です。
IPropertySelectionModelインターフェースには、以下のメソッドが定義されています。

  • getOptionCount()
  • getOption(int index)
  • getLabel(int index)
  • getValue(int index)
  • translateValue(String optionTagValue)

こいつが、サーバーサイドとクライアントサイドのデータのやり取りを行います。
大事なのは、どのメソッドがサーバーサイドのデータ用でどのメソッドがクライアントサイドのデータ用かを
認識しておくことです。

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.tapestry;

import java.util.*;

import org.apache.tapestry.form.*;

/**
 * IPropertySelectionModelの実装クラス.<br/>
 *
 * @author gsf_zero1
 *
 */
public class Select002PropertySelectionModel implements IPropertySelectionModel{

    /** モデル値 */
    private List<LabelValueBean> modelValue;

    /**
     * コンストラクタ.<br/>
     *
     * @param modelValue モデル値
     *
     */
    public Select002PropertySelectionModel(List<LabelValueBean> modelValue){
        this.modelValue = modelValue;
    }

    /**
     * Option値のカウントを返す.<br/>
     *
     * @see org.apache.tapestry.form.IPropertySelectionModel#getOptionCount()
     */
    public int getOptionCount() {
        return this.modelValue.size();
    }

    /**
     * 指定インデックスのOption値を返す.<br/>
     * この値はサーバーサイドのjavaメソッドにセットされる際にコールされる。<br/>
     *
     * @see org.apache.tapestry.form.IPropertySelectionModel#getOption(int)
     */
    public Object getOption(int index) {
        return this.modelValue.get(index);
    }

    /**
     * Optionのラベル値を返す.<br/>
     * この値は、HTML側のOptionタグのラベル名に使用される.<br/>
     *
     * @see org.apache.tapestry.form.IPropertySelectionModel#getLabel(int)
     */
    public String getLabel(int index) {
        LabelValueBean lb = (LabelValueBean) this.getOption(index);
        
        return lb.getLabel();
    }

    /**
     * Optionのvalue値を返す.<br/>
     * この値は、HTML側のOptionタグのvalue値に使用される.<br/>
     *
     * @see org.apache.tapestry.form.IPropertySelectionModel#getValue(int)
     */
    public String getValue(int index) {
        LabelValueBean lb = (LabelValueBean) this.getOption(index);
        
        return lb.getValue().toString();
    }

    /**
     * 該当する値から、モデル内の該当するオブジェクトを見つけだし、返す.<br/>
     * 引数に入ってくるのは、HTML側のOptionタグのvalue値.<br/>
     *
     * @see org.apache.tapestry.form.IPropertySelectionModel#translateValue(java.lang.String)
     */
    public Object translateValue(String optionTagValue) {
        return getOption(Integer.parseInt(optionTagValue));
    }
}

ここまでできたら、後はjavaファイルで定義するだけです。
[javaファイル]

//
// 処理に必要なゲッターとセッター
//
    public abstract IPropertySelectionModel getSelect002PropertySelectionModel();
    public abstract void setSelect002PropertySelectionModel(IPropertySelectionModel model);

    public abstract LabelValueBean getSelect002ModelValue();
    public abstract void setSelect002ModelValue(LabelValueBean value);

//
// 初期化処理
//
    public void pageBeginRender(PageEvent event){

        List<LabelValueBean> select002Values = new ArrayList<LabelValueBean>();
        select002Values.add(new LabelValueBean("選択してください", new Integer(0)));
        for(int i = 0; i < 5; i++){
            select002Values.add(new LabelValueBean(String.format("option_value_%d", (i + 1)), new Integer*1;
    }

//
// FORMのサブミット時にコールされるリスナ
//
    public void selectSample002FormSubmit(IRequestCycle cycle){
        System.out.println(this.getSelect002ModelValue());
    }

ドロップダウンの項目を選択してサブミットすると、選択したインデックスのデータオブジェクトが
セットされていることが確認できます。

ちょっと、応用すれば、たとえばibatisで取得したオブジェクトのリストを利用して
表示することもできます。要は、どの値をラベルとして表示し、どの値をvalue値として
利用するかを決定するだけです。

*1:i + 1)))); } this.setSelect002PropertySelectionModel(new Select002PropertySelectionModel(select002Values