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位かなぁ...