Unit04 - 表單點擊動作的處理 - Command Components
目標
- 瞭解產生可點擊元素的 JSF Facelet
- 瞭解點擊後, 如何在後端執行 JSF Managed bean 的方法, 處理使用者的互動
知識
Facelets
JSF 的 Command Components 相關的 facelet 標籤:
h:commandButton
: 顯示按鈕h:commandLink
: 顯示超連結(link)
Post Request
Command Component 被按下後, 使用 Post 的方式, 提交 Request 到應用程式伺服器.
如果要使用 Get Request 與應用程式伺服器溝通, 使用 h:button
或者 h:link
facelets.
Command Component 重要元件屬性
action
屬性: 綁定到 JSF Managed Bean 的方法, 執行 UI 互動邏輯, 完成後回傳要轉跳的頁面名稱字串. 此方法稱之為 Action Method, 必須符合以下的方法簽名:1
public String methodName()
- 若有傳遞請求參數給 Action Method, 請使用
f:param
facelet. actionListener
屬性: 綁定到 JSF Managed Bean 的方法, 處理 UI 互動過程中元件產生的事件, 如 Value Change Event. 元件的事件處理會在後面單元介紹.
User Story
刪除購物車內的清單項目
假設購物車上有數個品項. 使用者在結賬前可以刪除購物車內的項目.
- 進入畫面, 顯示購物車內的內容.
- 使用者點選項目旁邊的刪除按鈕.
- 系統刪除購物車內的此項目. 之後, 更新頁面
- 使用者按下 Reset 按鈕, 重置購物車內的內容
實作程序
Step. 建立 entities.Dish
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
49
50
51
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package entities;
/**
*
* @author user
*/
public class Dish {
private int id;
private String name;
private float price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Dish(int id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
public Dish(){
}
}
Step. 建立 managed_beans.CartHandler
處理刪除購物車內品項及重置內容的動作.
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
76
77
78
79
80
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package managed_beans;
import entities.Dish;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
/**
*
* @author user
*/
@Named(value = "cartHandler")
@SessionScoped
public class CartHandler implements Serializable {
private Map<Integer, Dish> dishes;
/**
* Creates a new instance of CartHandler
*/
public CartHandler() {
}
@PostConstruct
public void init(){
dishes = new HashMap<>();
dishes.put(1, new Dish(1, "宮堡雞丁", 70));
dishes.put(2, new Dish(2, "蜜汁排骨", 75));
dishes.put(3, new Dish(3, "香酥雞腿", 90));
dishes.put(4, new Dish(4, "炭烤排骨", 90));
}
/**
* Return the collection for the <code> value </code> attribute of the <code> ui:repeat </code> facelet.
* The name of a collection of items that this tag iterates over.
* The collection may be a List, array, java.sql.ResultSet, or an individual java Object. If the collection is null, this tag does nothing.
* @return
*/
public Dish [] getDishList(){
Dish[] availDishes = null;
availDishes = dishes.values().toArray(new Dish [0]);
return availDishes;
}
/**
* Action method to delete a item in the cart.
*/
public String delItem(){
//get the request map
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
Map<String, String> params = ec.getRequestParameterMap();
Integer id = 0;
if (null != params.get("ID")) {
id = new Integer(params.get("ID"));
}
if (this.dishes.containsKey(id)){
this.dishes.remove(id);
}
return null;
}
public String resetCart(){
this.init();
return null;
}
}
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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h1> </h1>
已選擇菜色:
<h:form>
<table>
<tr>
<th>Name</th>
<th>Price</th>
<th>Action</th>
</tr>
<ui:repeat value="#{cartHandler.dishList}" var="dish">
<tr>
<td>#{dish.id}</td>
<td>#{dish.name}</td>
<td>#{dish.price}</td>
<td> <h:commandButton action="#{cartHandler.delItem}" value="Del">
<f:param name="ID" value="#{dish.id}"/>
</h:commandButton> </td>
</tr>
</ui:repeat>
</table>
<h:commandButton action="#{cartHandler.resetCart}" value="Reset Cart"/>
</h:form>
</h:body>
</html>
複習問題
- 在 JSF 中, 如何取得請求內的參數(Parameter)呢?
- 在 JSF 頁面, 使用那個 facelet 可以傳遞請求參數? 如何和
h:commandButton
搭配使用呢? f:param
facelet 的name
和value
屬性有何作用?
參考資料
[1] Oracle, 2014. Chapter 3 Creating JSF Pages Using Facelets. In JAVA EE 6: Develop Web Applications with JSF: Student Guide, vol 1.