JSF 2.2: HTML5 friendly markup

HTML5 is probably one of the most used buzzwords in the web development world these days. But behind the hype there are some really useful features and enhancements making the life of web developers easier (and probably more exciting). There have been several community approaches to combine JSF and HTML5 but the official support starts with JSF 2.2. In this post of the series on JSF 2.2 I will show how to create HTML5 friendly markup with passthrough attributes and elements.

As a prerequisite for supporting HTML5, JSF 2.2 slightly changed the way Facelets files are handled. By default, JSF 2.2 always renders the HTML5 doctype <!DOCTYPE html> regardless of what is set in the source xhtml file. If you need the old JSF 2.1 behavior (passing through the doctype from the source) you have to change the way xhtml files are processed in the faces-config.xml like this (the complete list of processing modes can be found in the spec):

<faces-config-extension>
  <facelets-processing>
    <file-extension>.xhtml</file-extension>
    <process-as>xhtml</process-as>
  </facelets-processing>
</faces-config-extension>

Now that we have ensured that the doctype is correct, the next step is to have some real HTML5 content. For this, JSF 2.2 offers two (closely connected) concepts:

Pass-through Attributes

JSF 2.2 introduces the so-called pass-through attributes to support new and modified attributes defined in HTML5. Each JSF component can have a bunch of those attributes. Unlike normal attributes components do not process pass-through attributes. Instead, they are directly passed to the rendered output element.

Pass-through attributes make it possible to render HTML5 attributes (or any other attributes) which are not natively supported by the component. Therefore it is not necessary to change the existing standard components. As HTML5 is still work in progress (and might be for a long time) this saves lots of trouble.

Let’s have a look at two concrete HTML5 changes for the element input. The first one is the new attribute placeholder used to define a text that is displayed if the input is empty. The second one is the updated list of values for the type attribute with new types like email, date or number.

The easiest way to add pass-through attributes to a component is by putting them into the namespace http://xmlns.jcp.org/jsf/passthrough. This namespace is used like any other JSF namespace but now attributes are prefixed instead of elements. The following example shows a h:inputText component with two “normal” and two pass-through attributes.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head><title>JSF 2.2</title></h:head>
<h:body>
  <h:form id="form">
    <h:inputText id="email" value="#{bean.email}"
        pt:type="email" pt:placeholder="Enter email"/>
  </h:form>
</h:body>
</html>

Looking at the rendered code for the h:inputText from above shows all four attributes. The browser should show a HTML5 email input field with a placeholder (if it already supports these features anyway).

<input id="form:email" name="form:email"
    value="" placeholder="Enter email" type="email" />

JSF also allows adding pass-through attributes with f:passThroughAttribute as the following listing shows.

<h:inputText id="email" value="#{bean.email}">
  <f:passThroughAttribute name="type" value="email"/>
  <f:passThroughAttribute name="placeholder"
      value="Enter email"/>
</h:inputText>

Still not satisfied? There is one more! You can also add pass-through attributes coming from a managed bean property of type Map<String, Object> with f:passThroughAttributes.

<h:inputText id="email" value="#{bean.email}">
  <f:passThroughAttributes value="#{bean.attributes}"/>
</h:inputText>

With pass-through attributes it is also possible to use HTML5 custom data attributes (see [1] for details). The attribute data-required in the following listing has no special meaning and can be evaluated by a script for instance (also see the jsf22-examples on Github).

<h:inputText id="email" value="#{bean.email}"
    pt:type="email" pt:data-required="true"/>

Passthrough Elements

Traditionally, JSF hides the rendered HTML output from the developer by providing custom component tags. But with the increasing importance of client side technologies it is often relevant to know the page structure. JSF 2.2 provides a solution for this with the so-called pass-through elements.

With pass-through elements it is possible to build the view with HTML elements that are linked to component instances on the server side. To make an element a pass-through element, at least one of its attributes must be in the namespace http://xmlns.jcp.org/jsf. The following example shows a fully functional JSF page without any JSF tag.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:jsf="http://xmlns.jcp.org/jsf">
<head jsf:id="head"><title>JSF 2.2</title></head>
<body jsf:id="body">
  <form jsf:id="form">
    <input type="text" jsf:id="name"
        placeholder="Enter name"
        jsf:value="#{bean.name}"/>
    <button jsf:action="#{bean.save}">Save</button>
  </form>
</body>
</html>

What happens here? If at least one attribute is in the namespace http://xmlns.jcp.org/jsf, JSF adds a component to the tree and links it to this element. The type of the component is determined by the element name and an identifying attribute if the element name alone is not sufficient.

Let’s take a look at the head element from the listing above. As the attribute id is in the jsf namespace, JSF adds a h:head component to the tree for this element and passes the attribute directly to the component. In the same way body is transformed to h:body and form to h:form.

For the input element, JSF additionally considers the type attribute and transforms it to h:inputText. Now we have to take a closer look at the attributes again. id and value are prefixed with jsf and will be passed to the component directly. As the new HTML5 placeholder attribute is not prefixed it is not passed to h:inputText as normal attribute (it does not exist anyway) but as a pass-through attribute!

The complete mapping between HTML elements and JSF component tags is defined in the API documentation for class TagDecorator.

As JSF creates a component for pass-through elements we can add anything the transformed component supports (which may seem strange at first glance):

<input type="text" jsf:value="#{bean.name}">
  <f:validateLength minimum="3"/>
</input>

Additionally, if there is no direct mapping for the element, JSF creates a special component that supports ajax. With this in mind it is possible to add JSF ajax functionality to any (even HTML5) element as the following example shows:

<div jsf:id="clickCounter">
  Clicks: #{bean.clickCount}
  <f:ajax event="click" render="@this"
      listener="#{bean.inc}"/>
</div>

The source code for the JSF 2.2 series examples can be found in the JSFlive Github repository jsf22-examples (module jsf22-html5).

Further official details about JSF 2.2 can be found in the JavaServer Faces 2.2 spec (JSR 344).

Links:
[1]: HTML5 custom data attributes | html5 Doctor

About these ads

6 responses to “JSF 2.2: HTML5 friendly markup

  1. Hi Michael,

    Thanks for your coverage of JSF 2.2. You blog post and the GitHub repo have helped a lot with my current project.

    Thanks,
    Mark P Ashworth
    https://github.com/markash/carat

  2. hi,

    I have a question how to use the standard tag of html5, but I’ve tried unsuccessfully to use in rendering within the tag and the default icons of the “css font-awesome”, has a light on how to make the best way?

  3. Pingback: JSF-2.2-View Scope for CDI | mauroprogram's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s