Wednesday, January 11, 2012

Making JSF 2.0 Composite Components Ajax render-capable

If you for example have the following composite component in a JSF 2.0 Facelets XHTML template:

<sc:block title="Followers">

<h:panelGroup rendered="#{not empty userShow.user.followedByUsers}">

<ul>

<ui:repeat var="user" value="#{userShow.user.followedByUsers}">

<li><sc:user_link user="#{user}"/></li>

</ui:repeat>

</ul>

</h:panelGroup>

<h:panelGroup rendered="#{empty usefollowedByUsers}">

#{userShow.user.name} has no followers.

</h:panelGroup>

</sc:block>

and try do ajax render:

<a4j:commandButton value="Follow" action="#{userBean.follow(currentUser, userShow.user)}"

render="followPanel followers"

rendered="#{not currentUser.isFollowing(userShow.user)}"/>

This won't work for some reason. Wrong workaround is using a h:panelGroup and moving the id for ajax render there:

<sc:block title="Followers">

<h:panelGroup id="followers">

<h:panelGroup rendered="#{not empty userShow.user.followedByUsers}">

<ul>

<ui:repeat var="user" value="#{userShow.user.followedByUsers}">

<li><sc:user_link user="#{user}"/></li>

</ui:repeat>

</ul>

</h:panelGroup>

<h:panelGroup rendered="#{empty us.followedByUsers}">

#{userShow.user.name} has no followers.

</h:panelGroup>

</h:panelGroup>

</sc:block>

The correct solution is to put a #{cc.clientId} like below in the composite implementation:

<composite:implementation>

<section id="#{cc.clientId}" class="block">

<div class="block-inner clearfix">

<h2 class="block-title">#{cc.attrs.title}</h2>

<div class="block-content content">

<composite:insertChildren/>

</div>

</div>

</section>

</composite:implementation>

To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.