產生動態選單選項資料及儲存單選及複選資料
JSF 教學 Unit 03
目標
- 瞭解如何產生選單元素的選項資料
- 了解如何儲存單選或複選的資料
知識
- Selection Complnents 選項的產生:
f:selectItem
,f:selectItems
- 單選元件的使用:
h:selectBooleanCheckbox
,h:selectOneListBox
,h:selectOneMenu
,h:selectOneRadio
- 複選元件的使用:
h:selectManyCheckbox
,h:selectManyListBox
,h:selecyManyMenu
單選元件的 value
屬性:
h:selectBooleanCheckbox
的 value 屬性要綁定型態為boolean
的 JSF Managed Bean Property.h:selectOneXXX
的 value 屬性要綁定型態為String
的 JSF Managed Bean Property.h:selectManyXXX
的 value 屬性要綁定型態為String[]
或者Collection<String>
User Story
- 使用者進入頁面後, 頁面顯示菜單選項, 供使用者複選. 選單項目由 JavaBean 設定.
- 頁面顯示取餐方式, 外送或自取(單選).
- 顯示備註欄位供使用者輸入
- 按下 Submit 按鈕後, 紀錄訂單送出時間, 並將上述表單資料送到伺服端的 JSF Managed Bean 儲存.
- 之後, 轉跳頁面
showinfo
顯示先前輸入的資訊
實作程序
Step 建立一個存放訂單資訊的 entity class. 建立套件 entities
, 在套件中建立 MealOrder
class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package entities;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 餐點訂單
* @author user
*/
public class MealOrder {
String [] meals;
String deliveryMethod;
String notes;
Date orderDate;
public String[] getMeals() {
return meals;
}
public void setMeals(String[] meals) {
this.meals = meals;
}
public String getDeliveryMethod() {
return deliveryMethod;
}
public void setDeliveryMethod(String deliveryMethod) {
this.deliveryMethod = deliveryMethod;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
}
Step 建立 Managed Bean, 處理 index.xhtml
頁面上的 Submit
action. 建立套件 beans
, 在此套件中建立 MealOrderBean
bean, 其生命範圍為 SessionScoped
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package beans;
import entities.MealOrder;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.model.SelectItem;
/**
* 負責餐點 UI 的處理邏輯
* @author user
*/
@Named(value = "mealOrderBean")
@SessionScoped
public class MealOrderBean implements Serializable {
MealOrder mealOrder;
List<SelectItem> availMeals;
/**
* Initialize the bean with the <code>PostConstruct</code> annotation
*/
@PostConstruct
public void init(){
mealOrder = new MealOrder();
// 建立可用的餐點
this.availMeals = new ArrayList<>();
availMeals.add(new SelectItem("G", "雞腿飯"));
availMeals.add(new SelectItem("P", "排骨飯"));
availMeals.add(new SelectItem("K", "焢肉飯"));
}
public MealOrderBean() {
}
public MealOrder getMealOrder() {
return mealOrder;
}
public void setMealOrder(MealOrder mealOrder) {
this.mealOrder = mealOrder;
}
/** 傳回可選擇的餐點名稱
*/
public List<SelectItem> getAvailMeals() {
return availMeals;
}
public void setAvailMeals(List<SelectItem> availMeals) {
this.availMeals = availMeals;
}
/**
* Handle the order action.
* @return (String) Target page.
*/
public String handleOrder(){
// Add the current date to the order
mealOrder.setOrderDate(new Date());
return "showInfo?faces-redirect=true";
}
}
其中:
init()
註記@PostConstruct
, Container 會在注入MealOrderBean
類別實體後, 執行此方法以初始化此實體.
Step 建立 index.xhtml
:
<?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:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:outputText value="今日餐點"/>
<h:selectManyListbox value="#{mealOrderBean.mealOrder.meals}">
<f:selectItems value="#{mealOrderBean.availMeals}" />
</h:selectManyListbox>
<h:outputText value="取餐方式"/> <br />
<h:selectOneRadio value="#{mealOrderBean.mealOrder.deliveryMethod}">
<f:selectItem itemValue="S" itemLabel="自取" />
<f:selectItem itemValue="P" itemLabel="外送" />
</h:selectOneRadio> <br/>
<h:outputText value="備註"/>
<h:inputText value="#{mealOrderBean.mealOrder.notes}" /><br/>
<h:commandButton value="Submit" action="#{mealOrderBean.handleOrder()}" />
</h:form>
</h:body>
</html>
Step 建立 showInfo.xhtml
:
<?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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Show Order Content</title>
</h:head>
<h:body>
餐點:
<ul>
<ui:repeat value="#{mealOrderBean.mealOrder.meals}" var="meal">
<li>#{meal}</li>
</ui:repeat>
</ul>
取餐方式: <h:outputText value="#{mealOrderBean.mealOrder.deliveryMethod}" /> <br />
備註: <h:outputText value="#{mealOrderBean.mealOrder.notes}"/> <br/>
訂單日期 <h:outputText value ="#{mealOrderBean.mealOrder.orderDate}"> <br/>
<f:convertDateTime dateStyle="long" locale="zh-TW" />
</h:outputText>
</h:body>
</html>
問題與討論
- 如何使用 facelet 顯示型態為
Date
的 bean property? - 製作選擇元件的選項時, 要使用那一個 facelet ?
- 複選的選擇元件, 如
h:selectManyListBox
, 和 Bean Property 綁定時, 此 Bean Property 的型態需為何? @PostConstruct
註記的用途是什麼?
進一步閱讀
- Scholtz, B. and Tijms, A. 2018. Chapter 4 Form Components. In The Definitive Guide to JSF in Java EE 8: Building Web Applications with JavaServer Faces, Apress.