Câu trả lời
Có, hoàn toàn có thể dùng JSF + Facelets với HTML5. Facelets là View Declaration Language (VDL) mặc định của JSF 2.0+, hỗ trợ đầy đủ HTML5.
Yêu cầu về DOCTYPE
Facelets dựa trên XML, do đó cần document well-formed. HTML5 DOCTYPE đơn giản là đủ:
<!DOCTYPE html>
Không cần khai báo XML (<?xml version="1.0"?>) ở đầu trang.
Ví dụ trang JSF/Facelets với HTML5
<!DOCTYPE html>
<html lang="vi"
xmlns="https://www.w3.org/1999/xhtml"
xmlns:h="https://xmlns.jcp.org/jsf/html"
xmlns:f="https://xmlns.jcp.org/jsf/core"
xmlns:ui="https://xmlns.jcp.org/jsf/facelets"
xmlns:pt="https://xmlns.jcp.org/jsf/passthrough">
<h:head>
<title>#{msgs.pageTitle}</title>
<h:outputStylesheet library="css" name="style.css" />
<h:outputScript library="js" name="app.js" />
</h:head>
<h:body>
<header jsf:id="header">
<h1>#{msgs.siteName}</h1>
<nav>
<ul>
<li><h:link outcome="home" value="#{msgs.home}" /></li>
<li><h:link outcome="about" value="#{msgs.about}" /></li>
<li><h:link outcome="contact" value="#{msgs.contact}" /></li>
</ul>
</nav>
</header>
<main jsf:id="main">
<ui:insert name="content">Nội dung mặc định</ui:insert>
</main>
<footer jsf:id="footer">
<p>© 2024 #{msgs.companyName}</p>
</footer>
</h:body>
</html>
Sử dụng Pass-through Attributes (JSF 2.2+)
Namespace pt: cho phép truyền attribute HTML5 thuần túy đến client mà không cần component JSF tương ứng:
<html ... xmlns:pt="https://xmlns.jcp.org/jsf/passthrough">
<!-- HTML5 attributes tự động render ra client -->
<input type="email" pt:placeholder="Email của bạn" pt:required="required" />
<input type="date" pt:min="#{bean.minDate}" pt:max="#{bean.maxDate}" />
<div pt:data-user-id="#{user.id}" pt:data-role="#{user.role}">...</div>
<button pt:disabled="#{not bean.editable}" pt:aria-label="Lưu">Lưu</button>
Template Facelets (Master Template)
<!-- /templates/master.xhtml -->
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml"
xmlns:h="https://xmlns.jcp.org/jsf/html"
xmlns:ui="https://xmlns.jcp.org/jsf/facelets">
<h:head>
<title><ui:insert name="title">Default Title</ui:insert></title>
<ui:insert name="head" />
</h:head>
<h:body>
<header><ui:insert name="header">Default Header</ui:insert></header>
<main><ui:insert name="content">Default Content</ui:insert></main>
<footer><ui:insert name="footer">Default Footer</ui:insert></footer>
<ui:insert name="scripts" />
</h:body>
</html>
<!-- /pages/home.xhtml -->
<ui:composition template="/templates/master.xhtml"
xmlns="https://www.w3.org/1999/xhtml"
xmlns:ui="https://xmlns.jcp.org/jsf/facelets"
xmlns:h="https://xmlns.jcp.org/jsf/html">
<ui:define name="title">Trang chủ - My App</ui:define>
<ui:define name="content">
<section>
<h2>Chào mừng #{user.name}</h2>
<p>#{msgs.welcomeMessage}</p>
</section>
</ui:define>
</ui:composition>
Lưu ý về HTML4 vs HTML5
- HTML4 (XHTML 1.0): Bắt buộc well-formed XML, self-closing tags (
<br/>,<img/>), attribute phải có giá trị. - HTML5 với Facelets: Dùng
<!DOCTYPE html>, trình duyệt parse như HTML (không phải XML), nhưng Facelets vẫn yêu cầu template well-formed khi compile. - Self-closing tags: Trong template Facelets, viết
<br/>,<img/>,<input/>để well-formed. JSF sẽ render đúng HTML5 (không có /) ra trình duyệt.
Khắc phục lỗi thường gặp
| Lỗi | Nguyên nhân | Giải pháp |
|---|---|---|
| XML Parsing Error | Template không well-formed (thẻ không đóng, attribute không quote) | Kiểm tra tất cả thẻ đóng, attribute trong ngoặc kép |
| Namespace không nhận diện | Thiếu xmlns declaration | Thêm đầy đủ xmlns:h, xmlns:f, xmlns:ui, xmlns:pt |
| Pass-through không hoạt động | Dùng JSF < 2.2 hoặc sai namespace | Upgrade JSF 2.2+, dùng xmlns:pt đúng |
| HTML5 element không render | Dùng JSF component thay vì passthrough | Dùng pt:attribute trên thẻ HTML thuần |