いろいろ備忘録日記

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

Tapestry奮闘記-0018 (独自コンポーネントの作成-02)

今回は、BaseComponentを継承してコンポーネントを作成してみます。
AbstractComponentとBaseComponentの違いは、昨日の日記を参照してください。
http://d.hatena.ne.jp/gsf_zero1/20060726/1153879962

作成方法は、基本的に同じです。
違いは、テンプレートとなるHTMLファイルを用意すること。

[コンポーネントクラス]

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

import java.util.*;

import org.apache.tapestry.*;

/**
 * 指定されたカラム数と行数のテストテーブルをレンダリングするコンポーネント.<br/>
 *
 * @author gsf_zero1
 *
 */
public abstract class TestDataTableCreater extends BaseComponent{

    /**
     * カラム数を取得する.<br/>
     *
     * @return カラム数
     *
     */
    public abstract Integer getNumberOfColumns();

    /**
     * 行数を取得する.<br/>
     *
     * @return 行数
     *
     */
    public abstract Integer getNumberOfRows();

    /**
     * カラムデータを取得する.<br/>
     *
     * @return カラムデータ
     *
     */
    public abstract List<String> getTableColumnData();

    /**
     * カラムデータを設定する.<br/>
     *
     * @param tableColumnData カラムデータ
     *
     */
    public abstract void setTableColumnData(List<String> tableColumnData);

    /**
     * 行データを取得する.<br/>
     *
     * @return 行データ
     *
     */
    public abstract List<List<String>> getTableRowData();

    /**
     * 行データを設定する.<br/>
     *
     * @param tableRowData 行データ
     *
     */
    public abstract void setTableRowData(List<List<String>> tableRowData);

    /**
     * @see org.apache.tapestry.IComponent#renderComponent(IMarkupWriter, IRequestCycle)
     */
    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle){

        Integer columns = this.getNumberOfColumns();
        Integer rows    = this.getNumberOfRows();

        List<String> columnData = new ArrayList<String>();
        for(int i = 0; i < columns; i++){
            columnData.add(String.format("%s-%d", "カラム", (i + 1)));
        }

        List<List<String>> rowData = new ArrayList<List<String>>();
        for(int i = 0; i < rows; i++){
            List<String> values = new ArrayList<String>();

            for(int j = 0; j < columns; j++){
                values.add(String.format("%s-%d-%d", "行", (i + 1), (j + 1)));
            }

            rowData.add(values);
        }

        this.setTableColumnData(columnData);
        this.setTableRowData(rowData);

        //
        // 必ず親メソッドを呼ぶこと。
        // これを呼ばないと、画面にレンダリングされない。
        //
        super.renderComponent(writer, cycle);
    }

}

[コンポーネント定義ファイル]

<?xml version="1.0" encoding="Windows-31J"?>
<!DOCTYPE component-specification PUBLIC 
  "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">

<component-specification class="gsf.samples.tapestry.components.TestDataTableCreater"
                         allow-body="false"
                         allow-infomal-parameters="false">

    <!--
        パラメータ定義
    -->
    <parameter name="numberOfColumns" required="true"/>
    <parameter name="numberOfRows"    required="true"/>

    <!--
        プロパティ定義
    -->
    <property name="columnData"/>
    <property name="rowData"/>
    <property name="aValue"/>

</component-specification>

[テンプレートファイル]

<span jwcid="$content$">
    <table border="1">
        <tr>
            <th jwcid="@For" source="ognl:tableColumnData" value="ognl:columnData" element="th" nowrap>
                <span jwcid="@Insert" value="ognl:columnData"></span>
            </th>
        </tr>
        <tr jwcid="@For" source="ognl:tableRowData" value="ognl:rowData" element="tr">
            <td jwcid="@For" source="ognl:rowData" value="ognl:aValue" element="td">
                <span jwcid="@Insert" value="ognl:aValue"></span>
            </td>
        </tr>
    </table>
</span>

[ライブラリ定義ファイル]

    <component-type type="TestDataTableCreater" specification-path="classpath:/gsf/samples/tapestry/components/TestDataTableCreater.jwc"/>

[実行部分]

                    <!--
                    
                        独自コンポーネントを使用する。
                        (TestDataTableCreaterコンポーネントを使用。)

                    -->
                    <br/>
                    <hr/>
                    <div id="original_component_002" align="center">
                        <b>
                            独自コンポーネントを使用(2)<br/>
                            <br/>
                            TestDataTableCreaterコンポーネントを使用。<br/>
                            今回、カラム数10、行数20のテストテーブルを作成.<br/>
                        </b>
                        <br/>
                        出力:
                        <br/>
                        <span jwcid="@my:TestDataTableCreater" numberOfColumns="literal:10" numberOfRows="literal:20"></span>
                        <br/>
                        <br/>
                    </div>
                    <hr/>
                    <br/>

実行すると、10x20のテーブルが表示されます。
ちょっと応用すれば、DBからデータを取得して、それをページングする
独自コンポーネントとか作れそうですね。