Eclipse+JSF+JPAで作るアプリ(10)―Faceletsテンプレート

今回はログイン画面、ユーザ一覧を表示する画面を作ります。
作ったものの画面は以下の通りです。

ユーザー一覧:
f:id:tshix:20150726014308p:plain

ログイン画面:
f:id:tshix:20150726014852p:plain

両方同じテンプレートを使用していて、テンプレートはトップペイン、レフトペイン、ボトムペイン、コンテンツペインからできています。

Primefacesのコンポーネントを使っているだけですが、リッチに見えると思います。

  • トップ、レフトのメニューにはPrimefacesのコンポーネントを使用しています。
  • 今回は敢えて、コンテンツペインのログイン画面、テーブル表示にPrimefacesを使いません。次回差し替えたものと比較するためです。
  • 今回は、テンプレートの作り方に終始し、ソースコードについては触れません。次回にまとめます。

Primefacesの導入

Java - PrimeFacesの導入方法とテーマの変え方メモ - Qiitaに詳しい方法が載っています。参考にさせていただきました。

  • 以下のサイトからダウンロードします。2015年7月の最新は、5.2です。
 http://primefaces.org/downloads
 Community Downloadsから落とします。上のほうにあるのは、Eliteといって有償版です。
 最初間違えて落としそうになりましたので注意が必要です。
  • EclipseのWEB-INF/libに、ダウンロードしたprimefaces-5.2.jarをペーストします。

テンプレートの作成

Eclipseより、NetBeansを使うほうが便利そうだなと感じるのは、このテンプレート作成が自動化されている点です。

テンプレートを作成する上で、注目してほしいのは、以下のタグです。

タグ 説明
ui:insert テンプレートの上書きできる名前を定義します。
ui:define テンプレートクライアントで上書きする名前を指定します。
ui:include 別のファイルをインポートします。

1番で、テンプレートのパーツの名前を定義し、2番で上書きするのがテンプレート機能です。3番目はテンプレート機能とは直接関係しませんが、コンテンツを別に定義してインポートできるため、管理しやすい形になります。

JSF 2.0 の新機能概要とFacelets テンプレートのご紹介 | 寺田 佳央 - Yoshio Teradaを参考に以下のページを作っていきます。

テンプレートの作成

WebContent以下に、templateというフォルダを作成します。
そこに、mainTemplate.xhtml, top.xhtml, left.xhtml, bottom.xhtmlを作成します。
f:id:tshix:20150726021246p:plain

  • <ui:insert name="top">, <ui:insert name="left">, <ui:insert name="content">, <ui:insert name="buttom">;で領域を定義しています。
  • <table>,<tr>,<td>タグで領域の場所を定義しています。
  • <ui:include>タグでパーツのxhtmlをインポートしています。

mainTemplate.xml

<?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"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      >
<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Your Library</title>
</h:head>
<h:body>
	<table cellspacing="10px">
		<tr>
			<td id="top" colspan="3">
				<ui:insert name="top">
					<ui:include src="./top.xhtml" />
				</ui:insert>
			</td>
		</tr>
		<tr>
			<td id="left" valign="top">
				<ui:insert name="left">
					<ui:include src="./left.xhtml" />
				</ui:insert>
			</td>
			<td id="content" valign="top">
				<ui:insert name="content">
					Content
				</ui:insert>
			</td>

		</tr>
		<tr>
			<td id="bottom" colspan="3">
				<ui:insert name="bottom">
					<ui:include src="./bottom.xhtml" />
				</ui:insert>
			</td>
		</tr>
	</table>
</h:body>
</html>
テンプレートのパーツ作成

トップメニューtop.xhmtlの内容
f:id:tshix:20150726023004p:plain

  • <p:menubar>でメニューバーを定義しています。<p:submenu>, <p:menuitem>でグループメニュー、メニューを定義できます。
  • <p:menuitem>には、actionとurlを値として設定できます。
  • ログアウトメニューだけ、style="float:right"で右側へ寄せています。
  • icon属性でアイコンを指定しています。

アイコン一覧は、以下のURLです。
http://www.petefreitag.com/cheatsheets/jqueryui-icons/

top.xhmtl

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">
<h:form id="menubar">
	<p:menubar>
		<p:submenu label="個人設定" icon="ui-icon-wrench">
			<p:menuitem value="テーマ変更" icon="ui-icon-refresh"
				action="/changeTheme.xhtml">
			</p:menuitem>
		</p:submenu>
		<p:submenu label="リンク" icon="ui-icon-extlink">
			<p:menuitem value="Google" url="http://www.google.co.jp">
			</p:menuitem>
			<p:menuitem value="Yahoo Japan" url="http://www.yahoo.co.jp">
			</p:menuitem>
		</p:submenu>

		<p:submenu label="ログアウト" icon="ui-icon-close" style="float:right">
			<p:menuitem value="ログアウト" action="#{sessionInfo.logout}">
			</p:menuitem>
		</p:submenu>
	</p:menubar>
</h:form>
</html>

サイドメニューleft.xhtmlの内容。
f:id:tshix:20150726023924p:plain

  • <p:panelMenu>でアコーディオンメニューを定義しています。
  • <p:submenu>, <p:menuitem>は、上記topメニューと同じです。

left.xhmtl

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">
	
<h:form id="panelMenus">
	<p:panelMenu style="width:300px">
		<p:submenu label="映画" icon="ui-icon-note">
			<p:menuitem value="検索" action="/searchMovie.xhtml" icon="ui-icon-search" />
			<p:menuitem value="レンタル履歴" action="/lendHistory.xhtml"
				icon="ui-icon-cart" />
		</p:submenu>
		<p:submenu label="プロフィール" icon="ui-icon-person">
			<p:menuitem value="パスワード変更" action="/changePassword.xhtml"
				icon="ui-icon-heart" />
			<p:menuitem value="プロフィール変更" action="/changeProfile.xhtml"
				icon="ui-icon-arrowrefresh-1-w" />
		</p:submenu>
		<p:submenu label="レビュー" icon="ui-icon-star">
			<p:menuitem value="映画のレビュー検索" action="/searchReview.xhtml"
				icon="ui-icon-signal" />
			<p:menuitem value="映画をレビューする" action="/reviewMovie.xhtml"
				icon="ui-icon-star" />
		</p:submenu>
		<p:separator />
		<p:submenu label="管理">
			<p:submenu label="ユーザ" icon="ui-icon-home">
				<p:menuitem value="ユーザの編集" action="/editUser.xhtml"
					icon="ui-icon-pencil" />
			</p:submenu>
			<p:submenu label="映画" icon="ui-icon-disk">
				<p:menuitem value="映画の編集" action="/editMovie.xhtml"
					icon="ui-icon-pencil" />
			</p:submenu>
		</p:submenu>
	</p:panelMenu>
</h:form>

</html>

フッター(bottom.xhmtl)の内容。寺田さんのページ同様手抜きします。

 <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      >
<h:body>
このページはRuby on Railsで作成されていません。
</h:body>
</html>

さて、テンプレートとそのパーツを作成しました。次はテンプレートクライアントです。

テンプレートクライアント作成

ログイン画面と、ユーザ編集の2種類作成します。

  • WebContent直下に、index.xhtml(ログイン), editUser.xhml(ユーザ編集)
  • WebContent\Contentにコンテンツ(blank.xhtml, login.xhml, userlist.xhmtl)を用意します。

f:id:tshix:20150726024602p:plain

ログイン画面

  • <ui:composition template="./template/mainTemplate.xhtml">でテンプレートを使用することを宣言しています。
  • <ui:define name="xxx">で、テンプレートのtop,left,bottom領域をblank.xhtmlに、content領域をlogin.xhtmlに上書きしています。
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">
	
<ui:composition template="./template/mainTemplate.xhtml">
	<ui:define name="top">
		<ui:include src="./content/blank.xhtml"></ui:include>
	</ui:define>
	<ui:define name="left">
		<ui:include src="./content/blank.xhtml"></ui:include>
	</ui:define>
	<ui:define name="content">
		<ui:include src="./content/login.xhtml"></ui:include>
	</ui:define>
	<ui:define name="bottom">
		<ui:include src="./content/blank.xhtml"></ui:include>
	</ui:define>
</ui:composition>

</html>

ユーザ編集画面

  • <ui:define name="xxx">で、テンプレートのcontent領域をuserlist.xhtmlに上書きしています。
  • それ以外のtop,left,bottom領域はテンプレートのものを利用しています。(必要なところだけui:defineで上書き指定します)
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">

<ui:composition template="./template/mainTemplate.xhtml">
	<ui:define name="content">
		<ui:include src="./content/userlist.xhtml"></ui:include>
	</ui:define>
</ui:composition>

</html>
コンテンツのページ

login.xhtml

  • アカウント、パスワード、「ログイン」ボタンの3つから構成されています。
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">

<h2>Your Library</h2>
<h:form id="loginForm">
	<h:graphicImage url="./resource/image/top.jpg"/>
	<h:panelGrid columns="2">
		<h:outputText value="アカウント:" />
		<h:inputText value="#{loginView.account}" />

		<h:outputText value="パスワード:" />
		<h:inputSecret value="#{loginView.password}" />

		<h:commandButton value="ログイン" action="#{loginView.login}" />
	</h:panelGrid>
	<h:messages showDetail="true" style="color:red" />
</h:form>
</html>

userlist.xhtml

  • ユーザの追加と、一覧表示用の2つのフォームを持っています。(一覧表示用は、後で削除や編集機能を付けるためフォームとしています。)
  • h:dataTableタグで、ユーザ一覧をテーブル表示しています。
 <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      >
<h2>ユーザー編集</h2>
<h:form id="addUserForm">
	<h:panelGrid columns="2">
		<h:outputText value="アカウント:" />
		<h:inputText value="#{editUserView.account}" />

		<h:outputText value="名前:" />
		<h:inputText value="#{editUserView.name}" />

		<h:outputText value="パスワード:" />
		<h:inputText value="#{editUserView.password}" />

		<h:outputText value="E-mail:" />
		<h:inputText value="#{editUserView.email}" />

		<h:commandButton value="ユーザの追加" action="#{editUserView.addUser}" />
	</h:panelGrid>

	<h:messages />
</h:form>
<br />
<br />
<h2>ユーザー一覧</h2>
<h:form id="userListForm">
	<h:dataTable id="userList" var="user" value="#{editUserView.users}">
		<h:column>
			<f:facet name="header">
				<h:outputText value="アカウント" />
			</f:facet>
			<h:outputText value="#{user.account}" />
		</h:column>

		<h:column>
			<f:facet name="header">
				<h:outputText value="名前" />
			</f:facet>
			<h:outputText value="#{user.name}" />
		</h:column>

		<h:column>
			<f:facet name="header">
				<h:outputText value="e-mail" />
			</f:facet>
			<h:outputText value="#{user.email}" />
		</h:column>
	</h:dataTable>
</h:form>
</html>

コンテンツの詳細は次回、マネージドビーン(ManagedBean)とともに解説します。