產生動態選單選項資料及儲存單選及複選資料

3 minute read

JSF 教學

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

  1. 使用者進入頁面後, 頁面顯示菜單選項, 供使用者複選. 選單項目由 JavaBean 設定.
  2. 頁面顯示取餐方式, 外送或自取(單選).
  3. 顯示備註欄位供使用者輸入
  4. 按下 Submit 按鈕後, 紀錄訂單送出時間, 並將上述表單資料送到伺服端的 JSF Managed Bean 儲存.
  5. 之後, 轉跳頁面 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>
  
  

問題與討論

  1. 如何使用 facelet 顯示型態為 Date 的 bean property?
  2. 製作選擇元件的選項時, 要使用那一個 facelet ?
  3. 複選的選擇元件, 如 h:selectManyListBox, 和 Bean Property 綁定時, 此 Bean Property 的型態需為何?
  4. @PostConstruct 註記的用途是什麼?

進一步閱讀

  1. 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.

[Top]

Updated: