Shale Clay Plugin その5

今回は,Shale Clay Pluginで提供されているforEachコンポーネントを使用してみます.
JSTLやFaceletsやS2JSFなどでもforEachコンポーネントは提供されています.
ある程度使い方は想像できますね.
JSFのdataTableやfacetなどを記述するのは正直だるいので,うれしい機能です.

ソースと設定ファイル

listsearch.html

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>検索</title>
</head>

<body>
<form>
<h1>検索</h1>
<table border="1">
    <tr>
        <th>あああ</th>
        <td><input id="text1" type="text" value="#{@managed-bean-name.text1}" /></td>
    </tr>
    <tr>
        <th>いいい</th>
        <td><input id="text2" type="text" value="#{@managed-bean-name.text2}" /></td>
    </tr>
    <tr>
        <td colspan="2">
            <input id="search" type="submit" action="#{@managed-bean-name.doSearch}" />
        </td>
    </tr>
</table>

<div id="sub1" jsfid="f:subview"
    rendered="#{!empty @managed-bean-name.list}">
<h2>一覧</h2>
<table border="2">
    <tr>
        <th>あああ</th>
        <th>いいい</th>
    </tr>
    <span jsfid="clay:clayForEach" value="#{@managed-bean-name.list}" var="sessionList" bodyJsfid="/listtable.html" allowbody="false">
    <tr>
        <td>ほげほげ</td>
        <td>ふげふげ</td>
    </tr>
    </span>
</table>
</div>
</form>
</body>
</html>

listtable.html

<html xmlns="http://www.w3.org/1999/xhtml" jsfid="void">
<head jsfid="void" allowbody="false">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>ダミーテーブル</title>
</head>
<body jsfid="void">
<table border="2" jsfid="void">
    <tr jsfid="void" allowbody="false">
        <th>あああ</th>
        <th>いいい</th>
    </tr>
    <tr>
        <td><span id="aaa" jsfid="h:outputText" allowbody="false" value="#{@managed-bean-name.aaa}">ほげほげ</span></td>
        <td><span id="bbb" jsfid="h:outputText" allowbody="false" value="#{@managed-bean-name.bbb}">ふげふげ</span></td>
    </tr>
</table>

</body>
</html>

sample.ListSearchBean

package sample;

import java.util.ArrayList;
import java.util.List;

import logic.SearchLogic;

import org.apache.shale.view.AbstractViewController;

public class ListSearchBean extends AbstractViewController {
    private String text1_;

    private String text2_;

    private List list_ = new ArrayList();

    public String getText1() {
        return text1_;
    }

    public void setText1(String text1) {
        text1_ = text1;
    }

    public String getText2() {
        return text2_;
    }

    public void setText2(String text2) {
        text2_ = text2;
    }

    public List getList() {
        return list_;
    }

    public String doSearch() {
        SearchLogic logic = (SearchLogic) getValue("#{list}");
        list_ = logic.searchList();
        return null;
    }
}

sample.ListTableBean

package sample;

public class ListTableBean {

    private String aaa_;

    private String bbb_;

    public String getAaa() {
        return aaa_;
    }

    public void setAaa(String aaa) {
        aaa_ = aaa;
    }

    public String getBbb() {
        return bbb_;
    }

    public void setBbb(String bbb) {
        bbb_ = bbb;
    }
}

logic.SearchLogic

package logic;

import java.util.List;

public interface SearchLogic {
    public List searchList();
}

logic.searchLogicImpl

package logic;

import java.util.ArrayList;
import java.util.List;

import sample.ListTableBean;

public class SearchLogicImpl implements SearchLogic {

    public List searchList() {
        List list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            ListTableBean dto = new ListTableBean();
            dto.setAaa("あああ" + i);
            dto.setBbb("いいい" + i);
            list.add(dto);
        }
        return list;
    }

}

faces-config.xml

<managed-bean>
    <managed-bean-name>listsearch</managed-bean-name>
    <managed-bean-class>sample.ListSearchBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
    <managed-bean-name>list</managed-bean-name>
    <managed-bean-class>logic.SearchLogicImpl</managed-bean-class>
    <managed-bean-scope>singleton</managed-bean-scope>
</managed-bean>
<managed-bean>
    <managed-bean-name>listtable</managed-bean-name>
    <managed-bean-class>sample.ListTableBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

これで設定は終了です.

説明

今回は,いくつか説明する項目があります.

listsearch.html
<div id="sub1" jsfid="f:subview" rendered="#{!empty @managed-bean-name.list}">

これは,リストが空の場合表示しないという1行です.
今回はリストが空の場合は表示しないようにしていますが,初回表示のみ表示しないといったことも可能です.
この例ではspanではなくdivで囲っていますが,spanでも同様です.(divにjsfidを指定してもいけるのか試しただけです)

<span jsfid="clay:clayForEach" value="#{@managed-bean-name.list}" var="sessionList" bodyJsfid="/listtable.html" allowbody="false">

ここで,forEachを指定しています.
jsfidで,clayForEachを指定します.
valueは,繰り返す対象のリストを指定します.リスト以外にもマップ,配列等をサポートしています.
varは少し特殊です.
varで指定した名前でSessionスコープにリストが保存されます.
すなわち,'sessionList'でセッションスコープからゲットすると,valueで指定したリストを取得することが出来ます.
このあたりは,その他のforEachとは動きが異なりますね.
bodyJsfidは,繰り返しで呼ぶ対象です.この項目は必須となっています.
むむぅ.少しむづかしいですね.

listtable.html

このHTMLが繰り返し項目で呼ばれる中身です.

jsfid="void"

となっている場所が沢山あります.
jsfidにvoidを指定すると,レンダリングの対象となりません.
モックアップ等で表示したくないダミーの部分を指定するのに使用されます.
(実際には,StateHolderのisTransientにtrueを設定して,ステートの保存と復元をしないようにしています.)

allowbody="false"

allowbodyにfalseを設定すると,このタグで囲われた中身を削除します.
これも,モックアップ等ダミーの表示に使用されることが多いと思います.

よって,このHTMLは,

<tr>
    <td><span id="aaa" jsfid="h:outputText" allowbody="false" value="#{@managed-bean-name.aaa}">ほげほげ</span></td>
    <td><span id="bbb" jsfid="h:outputText" allowbody="false" value="#{@managed-bean-name.bbb}">ふげふげ</span></td>
</tr>

を表示したいだけです.その他は,モックアップ用のダミーとなります.
listsearch.htmlのclayForEachで囲われた中身に上記の内容を繰り返し差し込んでいきます.

sample.ListSearchBean

このBeanは,listsearch.htmlのバッキングビーンです.

 extends AbstractViewController

となっています.これはViewControllの章でまた説明しますが,簡単に説明すると,
バッキングビーンのヘルパークラスと言った感じでしょうか.
FacesContextやExternalContextなどを便利に扱うヘルパーや,ライフサイクルの拡張ポイントなどが含まれています.
また,そのうち.

SearchLogic logic = (SearchLogic) getValue("#{list}");

getValue()では,faces-config.xmlに定義してあるマネージドビーンを取得することができます.
今は,気にする必要はないでしょう...
ようするに,logicクラスを取得した.と...

sample.ListTableBean

これは,繰り返しで表示している部分のバッキングビーンとなります.

logic.SearchLogic

一応,インターフェースを定義して,実装を書くようにします.
Implでは,リストを生成しています.
実際は,DBアクセスを行ってリストを取得するようにするのでしょうが,今回はダミーで10個作成しました.

表示する.

http://localhost:8080/sample/listsearch.html

にアクセスします.
サブミットすると,一覧が出力されます.

以上で終わり.

後は,Token位かなぁ...