概要
JSFのテンプレートに思った以上に苦戦したので
私なりにまとめてみました。
理解してみれば実にシンプルな内容でした。
環境
- IDE : Eclipse 4.7 Oxygen
- APサーバ : GlassFish 4.1.1
- JDK 1.8
- OS : Windows7
- プロジェクトの設定
対象読者
- Facelets(JSF)初心者
実装
このTmeplateSampleページは左右共に
4つのxhtmlファイルを組み合わせて作成されています。
- index.xhtml or board.xhtml (コンテンツ要素)
+
- header.xhtml(ヘッダー要素)
- left.xhtml(メニュー要素)
- footer.xhtml(フッター要素)
そしてこれら要素をどういった形で組み合わせるか定義しているものがテンプレートです。
- template.xhtml
パターン1
まずはテンプレートから。
<ui:insert>
タグとname属性を用いて、要素(ヘッダーとかフッターとか)を入れる場所を設定します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<div align="center">
<table border="1">
<tr>
<td colspan="2"><ui:insert name="header" /></td>
</tr>
<tr>
<td><ui:insert name="left" /></td>
<td><ui:insert name="content" /></td>
</tr>
<tr>
<td colspan="2"><ui:insert name="footer" /></td>
</tr>
</table>
</div>
</h:body>
</html>
これで基本的なページのレイアウトがtemplate.xhtml
に定義されました。
次に各要素を準備します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<h2>Template Site</h2>
</h:body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
Copyright 2017 ○○.
</h:body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<ul>
<li><a href="index.xhtml">TOP</a></li>
<li><a href="board.xhtml">掲示板</a></li>
</ul>
</h:body>
</html>
ヘッダー、フッター、メニュー要素が出来ました。
次にテンプレートを利用する、メインとなるページを作成します。
<ui:conposition>
タグを利用し、template属性にテンプレートとなるxhtmlを指定します。
<ui:define>
タグのname属性で、テンプレートの<ui:insert>
タグのname属性で設定した要素を挿入する場所を指定します。
必要であれば、<ui:include>
タグのsrc属性で利用する要素(xhtmlファイル)を指定します。
共通部分でなければui:define
タグの中に、コンテンツ内容を記述します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<!-- 利用するテンプレートを宣言 -->
<ui:composition template="template.xhtml">
<!-- テンプレートのnameに対応した位置に読み込みたいxhtmlを設定 -->
<ui:define name="header">
<ui:include src="header.xhtml" />
</ui:define>
<ui:define name="left">
<ui:include src="menu.xhtml" />
</ui:define>
<ui:define name="footer">
<ui:include src="footer.xhtml" />
</ui:define>
<!-- ここからメインコンテンツ -->
<ui:define name="content">
<h:inputText value="#{indexBean.mainText}" style="color:blue" />
</ui:define>
</ui:composition>
</h:body>
</html>
掲示板ページも同様に記述します。
メインコンテンツ以外はindex.xhtml
と共通のヘッダー、フッター、メニューを利用しています。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<!-- 利用するテンプレートを宣言 -->
<ui:composition template="template.xhtml">
<!-- テンプレートのパーツ名に対応した位置にxhtmlを読み込み(header) -->
<ui:define name="header">
<ui:include src="header.xhtml" />
</ui:define>
<ui:define name="left">
<ui:include src="menu.xhtml" />
</ui:define>
<ui:define name="footer">
<ui:include src="footer.xhtml" />
</ui:define>
<!-- ここにメインコンテンツ -->
<ui:define name="content">
<h:inputTextarea value="#{indexBean.boardArea}" style="color:green" />
</ui:define>
</ui:composition>
</h:body>
</html>
最後に管理Beanです。
package bean;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class IndexBean {
private String mainText = "メインコンテンツ";
private String boardArea = "掲示板";
public String getMainText() {
return mainText;
}
public void setHeaderText(String mainText) {
this.mainText = mainText;
}
public String getBoardArea() {
return boardArea;
}
public void setBoardArea(String boardArea) {
this.boardArea = boardArea;
}
}
パターン2(テンプレートに直接要素を埋め込む)
header.xhtml
fooer.xhtml
menu.xhtml
及び管理Beanはパターン1と同一です。
パターン1の場合、埋め込むファイル名等に変更があった場合、
全てのコンテンツファイル(index.xhtmlやboard.xhtml)を変更しなければなりません。
パターン2のようにテンプレートに要素を直接埋め込むことで、
ファイル名に変更があってもテンプレート(template.xhtml)1つを編集するだけで済みます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<div align="center">
<table border="1">
<tr>
<td colspan="2"><ui:include src="header.xhtml"/></td>
</tr>
<tr>
<td><ui:include src="menu.xhtml"/></td>
<td><ui:insert name="content" /></td>
</tr>
<tr>
<td colspan="2"><ui:include src="footer.xhtml"/></td>
</tr>
</table>
</div>
</h:body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<!-- 利用するテンプレートを宣言 -->
<ui:composition template="template.xhtml">
<!-- メインコンテンツ -->
<ui:define name="content">
<h:inputText value="#{indexBean.mainText}" style="color:blue" />
</ui:define>
</ui:composition>
</h:body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>TemplateSample</title>
</h:head>
<h:body>
<!-- 利用するテンプレートを宣言 -->
<ui:composition template="template.xhtml">
<!-- ここにメインコンテンツ -->
<ui:define name="content">
<h:inputTextarea value="#{indexBean.boardArea}" style="color:green" />
</ui:define>
</ui:composition>
</h:body>
</html>
パターン1と同様の表示結果になります。
注意点として
index.xhtml
、board.xhtml
等テンプレートを利用しているソースは
<ui:composition>
タグの外にコンポーネントを配置しても反映されません。
テンプレートは利用するけど、テンプレートの外にもコンポーネントを配置したい!という場合は
<ui:decorate>
タグを使うそうです。