After Java EE 7 and the release of JSF 2.2, the framework always renders the HTML5 document type: <DOCTYPE html>
. This is the default behavior for the modern digital websites. With the HTML5 support, developers can just write the content in a Facelets view (a *.xhtml
file) that is compatible with the rendering engines in a modern web browser.
JSF 2.2 provides two types of attributes for the HTML elements: pass-through
attributes and pass-through
elements.
The pass-through
attributes enable JSF to seamlessly support the new and extended attributes that are defined by the HTML5. These attributes are applicable to the JSF HTML render kit custom tags such as <h:inputText>
. In order to use the pass-through
attributes, we will define a JSF namespace at the top of the Facelets view that references the URL http://xmlns.jcp.org/jsf/passthrough.
Let's take an example that uses the HTML5 attributes for a placeholder text:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://xmlns.jcp.org/jsf/passthrough"> ... <div class="form-group"> <label for="birthday" class="col-sm-3 control-label"> Birthday </label> <div class="col-sm-9"> <h:inputText p:type="date" class="form-control" id="birthday" value="#{customerController.birthday}" p:placeholder="1977-10-25"/> </div> </div> <div class="form-group"> <label for="email" class="col-sm-3 control-label"> Email </label> <div class="col-sm-9"> <h:inputText p:type="email" class="form-control" id="email" value="#{customerController.email}" p:placeholder="[email protected]"/> </div> </div>
The pass-through
attribute in the preceding example is demarcated with the full namespace, p:placeholder
and p:type
. One input field annotates for the date format and the other for the e-mail address. The value of placeholder provides the customer/user with a visual hint about how to fill in the field. The JSF render kit will pass this attribute minus the XML namespace to the rendered tag output. The value of type overrides the default render kit setting.
Some JavaScript frameworks also rely on extended attributes such as AngularJS or certain JQuery plugins. JSF allows page content writers and interface developers to pass these values as attributes. The value of the pass-through attribute may be dynamic and can also be derived from an EL. We can thus write the following markup to validate for a secured loan amount:
<h:inputText p:type="range" class="form-control" id="loanAmount" value="#{customerController.loanAmount}" p:min="#{loanHelper.min}" p:max="#{loanHelper.max}" p:step="#{loanHelper.step}" p:placeholder="Decimal number between {loanHelper.min} and {loanHelper.max}"/>
With the preceding code extract, the pass-through
attribute p:type
as a range value causes the modern browsers to render a slider control instead of a text control. There is a backing bean named loanHelper
that dynamically supplies the minimum, maximum, and step unit values to the control.
The drawback of the pass-through
attributes is that they do not look at the standard HTML5 attributes that are available in a modern web browser. An input field that is defined with a rapid UX markup such as <h:inputText>
is not directly viewable by a stakeholder client without a microservice already running in the background process.
To enable the pass-through
elements in our Facelets view, we must first define the JSF namespace http://xmns.jcp.org/jsf
. In order to trigger a pass-through
element, at least one of the attributes of an HTML element must be in the namespace.
Let's see how this works in practice with a Facelets view:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsf="http://xmlns.jcp.org/jsf"> <head jsf:id="head"> ... </head> <body jsf:id="body"> ... <form jsf:id="vacationForm"> ... <input type="text" jsf:id="companyId" placeholder="Your company identity number" jsf:value="#{vacationController.companyNo}"/> <input type="text" jsf:id="lastName" placeholder="Enter last name" jsf:value="#{vacationController.name}"/> ... <button class="btn btn-primary" jsf:action="#{vacationController.makeRequest}"> Make Vacation Request</button> </form> </body> </html>
The HTML elements—head
, body
, form
, input
, and button
—have at least one JSF namespace attribute. JSF detects the attribute and adds a component to its rendering tree. The name of the element determines the type of the component that is added. So, the head element is in fact rendered by the equivalent of the <h:head>
custom tag, and the body element is also rendered by the equivalent JSF <h:body>
custom tag. The HTML input type is treated specially and rendered with <h:inputText>
. The id
and value
attribute are passed with the JSF namespace. The placeholder attributes are passed as normal attributes without the JSF namespace. They are surprisingly supplied and treated like pass-through
attributes!
We can add validation to what looks like normal HTML5 elements. Here is the code to ensure that the user enters at least six characters:
<input type="text" jsf:id="companyId" placeholder="Your company identity number" jsf:value="#{vacationController.companyNo}"/> <f:validateLength minimum="6" /> </input>
We will insert <f:validateLength>
as the direct body content of the HTML input element. The HTML5 support ensures that the tag is translated as a JSF input component. The support also extends to the AJAX tags and library functions.