#はじめに
JSFプログラミングにてFormからDialogをポップアップさせて、Dialog上のコンボボックス(selectOneMenu)の選択結果を元のフォームに反映させる方法の紹介です。
JavaEE上の開発になりますが、アプリケーションサーバにGlassFish、DialogのライブラリにPrimeFacesを使用しています。IDEはnetbeansを使っています。
NetBeansインストール方法はこちらを参照ください。
Projectの作成、PrimeFaces設定方法はこちらを参照下さい。
JavaEEの入門にはこちらがおススメです。
選択ボタンをクリックするとチーム一覧が表示され、任意チームのselectボタンをクリックすると一覧画面が閉じてフォームに入力される画面を作ってみました。
#環境
NetBeans 8.0.2
JavaSDK 1.8.0.25
PrimeFaces 5.0
GlassFish 4.1
#configファイル追加
PrimeFacesのマニュアルに記載されていますが、DialogFrameworkを有効とするためfaces-config.xmlファイルをWEB-INFフォルダに作成します。そして以下のエントリを追加します。
<application>
<action-listener>org.primefaces.application.DialogActionListener</action-listener>
<navigation-handler>org.primefaces.application.DialogNavigationHandler</navigation-handler>
<view-handler>org.primefaces.application.DialogViewHandler</view-handler>
</application>
#Dialogの表示
PrimeFacesのDialogFrameworkを利用すれば、作成したJSF画面をDialogとして表示することができます。BackingBeanではDialogとして表示したいJSFページをopenDialogメソッドの引数に指定します。
public void viewTeams() {
RequestContext.getCurrentInstance().openDialog("viewTeams");
}
Dialogの親フォームではcommandButtonのリスナーにメソッドを指定し、ButtonClickの契機でDialogを表示させます。
<p:commandButton value="選択" actionListener="#{bb.viewTeams()}" />
#Dialogの入力結果取得
dataTableの選択イベントにて、DialogFrameworkのcloseDialogメソッドを呼ぶことでDiaolgのクローズと親フォームへの選択結果渡しが同時にできます。
public void selectTeamFromDialog(String teams) {
RequestContext.getCurrentInstance().closeDialog(teams);
}
親フォームではDialog選択結果を受け取るため、ajaxタグを使用してdialogReturnイベントをフックします。選択結果はBackingBeanのメンバに格納するためlistenerを指定します。また、メンバの内容を表示するinputTextのidをupdateに指定します
<p:commandButton value="選択" actionListener="#{bb.viewTeams()}" >
<p:ajax event="dialogReturn" listener="#{bb.handleReturn}"
update="inputTeam" />
</p:commandButton>
BackingBeanではSelectEvent型の引数から選択結果を取得します。
public void handleReturn(SelectEvent event) {
team = (String) event.getObject();
}
#プログラムコード
##JSF
ファイル名 | 説明 |
---|---|
index.xhtml | 親Formのページ |
viewTeams.xhtml | Dialogとして表示されるページ |
<?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:p="http://primefaces.org/ui">
<h:head>
<title>favorite team</title>
</h:head>
<h:body>
<h:form id="form1">
好きなチームは?
<h:inputText id="inputTeam" value="#{bb.team}" />
<p:commandButton value="選択" actionListener="#{bb.viewTeams()}" >
<p:ajax event="dialogReturn" listener="#{bb.handleReturn}" update="inputTeam" />
</p:commandButton>
</h:form>
</h:body>
</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"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Teams</title>
<style type="text/css">
.ui-widget {
font-size: 90%;
}
</style>
</h:head>
<h:body>
<h:form>
<p:selectOneMenu value="#{teamList.league}">
<f:selectItem itemValue="セリーグ" itemLabel="セリーグ" />
<f:selectItem itemValue="パリーグ" itemLabel="パリーグ" />
<p:ajax event="change" update="teamTable" />
</p:selectOneMenu>
<p:dataTable id="teamTable" var="team" value="#{teamList.teams}" style="width:200px">
<p:column headerText="チーム" style="width:50px;text-align: center">
<h:outputText value="#{team}" />
</p:column>
<p:column headerText="select" style="width:32px;text-align: center">
<p:commandButton icon="ui-icon-search"
actionListener="#{bb.selectTeamFromDialog(team)}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
##Java
ファイル名 | 説明 |
---|---|
Bb.java | 親FormとDialogのBackingBean |
TeamList.java | DialogのdataList用メンバを生成して保持する |
package beans;
import java.util.*;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
@Named()
@RequestScoped
public class Bb {
String team;
public void viewTeams() {
Map<String,Object> options = new HashMap<>();
options.put("width", 250);
RequestContext.getCurrentInstance().openDialog("viewTeams",options,null);
}
public void selectTeamFromDialog(String teams) {
RequestContext.getCurrentInstance().closeDialog(teams);
}
public void handleReturn(SelectEvent event) {
team = (String) event.getObject();
}
public void selectTeam(String team) {
this.team=team;
}
public String getTeam() {
return team;
}
public void setTeam(String team) {
this.team = team;
}
}
package beans;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class TeamList {
private List<String> teams=new ArrayList();
private String league;
@PostConstruct
public void init(){
league="セリーグ";
changeLeague();
}
public List<String> getTeams() {
return teams;
}
public void setTeams(List<String> teams) {
this.teams = teams;
}
public String getLeague() {
return league;
}
public void setLeague(String league) {
this.league = league;
changeLeague();
}
public void changeLeague() {
if(league == null)return;
if(league.equals("セリーグ") ){
teams=new ArrayList();
teams.add("スワローズ");
teams.add("ジャイアンツ");
teams.add("タイガース");
teams.add("カープ");
teams.add("ドラゴンズ");
teams.add("ディーエヌエー");
} else{
teams=new ArrayList();
teams.add("ホークス");
teams.add("ファイターズ");
teams.add("マリーンズ");
teams.add("オリックス");
teams.add("ライオンズ");
teams.add("ゴールデンイーグルス");
}
}
}
Poolから使用済みのbeanが割り当てられる可能性があるので、PostConstructアノテーションを指定したinitメソッドで初期化を行っています。
#終わりに
簡単な画面制御と値の受け渡しでしたが、javascriptを使うことなくコード作成出来ました。フレームワークではタグライブラリなど使用するとjavascriptを自動生成するケースが有るので、直接javascriptを書く場合はフレームワークとの連携が難しい場合が有りました。javascriptで書いていた部分をPrimeFacesがフォローする分、スッキリとしたコードになりました。