Unit 09 - 在 Facelets Page 中使用 HTML 5 元素

2 minute read

目標

  • 瞭解如何將 HTML 5 標籤標示成為 Facelets Tag (Pass-Through element)
  • 瞭解如何在 Facelets Tag 中使用 HTML 5 標籤的元素 (Pass-Throuth attribute)

知識:

JSF 2.2 之後可以將 HTML 5 的元素或者特定的元素屬性送進去 JSF Engine 中處理.

Use Case 1: 在 Facelets Page 中使用 HTML 5 的”年-月”輸入元素

1
2
3
4
<label for="start">Start month:</label>
  
<input type="month" id="start" name="start"
       min="2018-03" value="2018-05">

Ref: <input type="month"> @ developer.mozilla.org

要將此元素送進去 JSF engine 處理, 要使用 http://xmlns.jcp.org/jsf namespace.

1
2
3
  
<label for="month">Expired Date</label>
 <input jsf:id="month" type="month" value="#{processCard.expireDateStr}" />

<input> 中使用了 jsf namespace, JSF engine 處理此元素時, 會將之視為 Facelets 元素, 為其建立相對應的 Facelets Tag. 所以, 我們可以在 <input> 中使用 EL 語法將元素屬性和 Bean 的屬性綁定在一起。

這種元素我們稱之為 Pass-Through Element。

JSF Engine 處理 Pass-Through Element 時會自動為 HTML 5 元素建立對應的 Facelets 元素, 兩者之間的對應關係參考 Table 8-4 How Facelets Renders HTML5 Elements

例如, <a jsf:action=#{bean.actionMethod}> Click </a> 會產生相對應的 <h:commandButton action=#{bean.actionMethod}>

Use Case 2: 在 Facelet Tag 中使用 HTML 5 Input 的 placeholder 屬性

HTML 5 Input 提供 placeholder 屬性 HTML input placeholder Attribute.

但此屬性在 <h:InputXXX> 類別的 facelets tag 尚未支援. 要在 JSF Enging render 出來的結果中正確顯示此 placeholder 屬性, 必須將其送入 JSF Enging 中. 此種元素屬性稱之為 Pass-Through Attribute.

此時, 使用 http://xmlns.jcp.org/jsf/passthrough namespace, 將特定的元素屬性標示為 Pass-Through Attribute。此元素會和 Facelet Tag 一起進入 JSF Engine, 並在 render 結果中出現.

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:jsf="http://xmlns.jcp.org/jsf"
      xmlns:ps="http://xmlns.jcp.org/jsf/passthrough"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
      ...
      <label for="form:card"> Card: </label>
                <input jsf:id="card" type="text" label="Card"
                       value="#{processCard.card}"
                       required="true"
                       requiredMessage="長度至少 13 碼"
                       ps:placeholder="長度至少 13 碼"
                       >
                    <f:validateLength minimum="13"/>
     </input>
</html>

另外, 也可以使用 f:passThroughAttribute 傳送單個 HTML Element 屬性, 或者 f:passThroughAttributes 傳送多個屬性。參考 8.9 HTML5-Friendly Markup - Java Platform, Enterprise Edition: The Java EE Tutorial (Release 7)

實作練習

修改 Unit08 練習中的 fillCreditCardForm.xhtml:

  1. 將表單中的 Amount 欄位該成使用 <input type="number">輸入數字.
  2. 將表單中的 Card 欄位加入 placeholder 屬性, 顯示 “長度至少 13 碼”

修改後的結果如下:

<?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"
      xmlns:jsf="http://xmlns.jcp.org/jsf"
      xmlns:ps="http://xmlns.jcp.org/jsf/passthrough"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title>Unit08: Fill form</title>
    </h:head>
    <h:body>
        <h1>填寫信用卡</h1>
        <h:form id="form">
            <h:panelGrid columns="3">
                Amount"
                <input jsf:id="amount" type="number" label="Amount"
                       value="#{processCard.amount}"
                       required="true">
                    <f:convertNumber minFractionDigits="2" />
                    <f:validateDoubleRange minimum="10" maximum="10000"/>
                </input>
  
                <h:message for="amount" styleClass="errorMessage"/>
  
                <label for="form:card"> Card: </label>
                <input jsf:id="card" type="text" label="Card"
                       value="#{processCard.card}"
                       required="true"
                       requiredMessage="長度至少 13 碼"
                       ps:placeholder="1234567890123"
                       >
                    <f:validateLength minimum="13"/>
                </input>
                <h:message for="card" styleClass="errorMessage"/>
  
                Expired Date (HTML 5 Month element):
                 <input jsf:id="month" type="month" value="#{processCard.expireDateStr}" />
  
            </h:panelGrid>
            <h:commandButton value="Process" action="/result" />
            <h:commandButton value="Cancel" action="/index" immediate="true" />
        </h:form>
  
  
  
    </h:body>
</html>
  
  

複習問題

  1. 什麼是 “Pass-Through Element” ? 為什麼要設計此功能? 使用情境為何?
  2. 什麼是 “Pass-Through Attribute” ? 為什麼要設計此功能? 使用情境為何?

技術挑戰

PrimeFaces 的 p:inputText 有支援 placeholder 屬性. 此外, 還有提供豐富的輸入元件. 嘗試將 fillCreditCardForm.xhtml 上的輸入改成 PrimeFaces 的輸入元件. 參考: PrimeFaces Showcase

相關文章

Updated: