Thursday, November 21, 2013

Use Icon for bootstrap Button in JSF 2.2

In JSF 2.1, it is not easy add an icon for h:commandButton if Bootstrap is used.  Here is the problem.
An icon is an HTML element inside a Button element in Bootstrap like this
<button >
<span class="glyphicon glyphicon-plus"></span>
</button>
But  h:commandButton is rendered as <input type="button"> in JSF 2.1. No child HTML element is allowed.

Rendering approach in JSF 2.1

Before JSF 2.1, the Renderer takes over outputing html. You, as page author, only passes the attributes. Renderer will take care of your attributes when outputing html. This approach is apparently not flexible enough. For example, html5 introduces some new attributes. Other client framework like AngularJS also introduces new attributes and tag to html. Facelet renderer has no idea about these attributes and silently ignored them.

Rendering approach in JSF 2.2

In JSF 2.2, another approach is added. It is the passthrough attributes and elements. In this approach, you specify what you html looks like. The final html is exactly like the facelet file. Here I focus on Passthrough element.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
  >
<h:head>
</h:head>
<h:body>
            <h:form id="test">                <!--  test passthrough element -->
                <button type="submit" jsf:id="testbtn" jsf:action="#{project.setup}">
                    <span class="glyphicon glyphicon-plus"></span>
                    Setup
                </button>

            </h:form>
  </h:body>
</html>


In this example, the button element comes from html namespace. It should be very familiar to any web developer. The interesting part is two jsf: attributes: jsf:id and jsf:action. These two attributes asks JSF facelet subsystem to perform its tricks: data-binding or action-binding.  So how can the subsystem knows the button element from html namespace is a commandButton in facelet. The html element mapping to JSF component tree is done at component tree building time. For detailed document, please consult the TagDecorator class JavaDoc.  It is worthwhile to mention again you control the final HTML completely. You do not rely mysterious Renderer from JSF implementation do output HTML.

It is cool, isn't it?



5 comments:

  1. wao ! That's what I am looking for ... To match bootstrap with my JSF development.
    As described, we don't need to create custom components library to control bootstrap components using JSF controllers ? was wandering the need of a component library support ...
    Thanks for the info. I will test it.

    ReplyDelete