Ajaxify composite component collapsiblePanel

In my last posts about the composite component collapsiblePanel I showed you how to make it self-contained and reusable and how to put it into a custom component library. The only thing that remains to do is to add some ajax behavior. As we are using JSF 2.0 this is actually easy to accomplish.

Currently, every click on the button results in a complete page refresh. The goal is to collapse and expand the panel with ajax. The intended behavior is that a click on the the button just updates the button itself (we need to change from plus to minus and vice versa) and the content panel.

The first step is to prepare the content panel. So far this panel was a simple h:panelGroup component with a rendered attribute. This approach won’t work with ajax. Components that should be updated with ajax must always be rendered. Otherwise the component has no representation in the DOM tree and cannot be updated.

The simplest solution for this is to place a second h:panelGroup component around the existing one. The following listing shows the updated content panel section.

<h:panelGroup id="panel-content" layout="block">
  <h:panelGroup rendered="#{!cc.collapsed}">

The second step is to add ajax behavior to the h:commandButton component. This is done by adding f:ajax as child element to the button. The attribute render takes a list of component IDs that should be rendered and updated as a result of the ajax request. In our case the attribute contains two IDs: @this stands for the component triggering the request (the button) and panel-content for the content panel. The following listing shows the code (without images and style):

<h:commandButton id="toggle" actionListener="#{cc.toggle}">
  <f:ajax render="@this panel-content"/>

The next listing shows the f:ajax tag with additional attributes. event specifies the event triggering the ajax request (action mapps to onclick for command components). execute takes a list of IDs for which the lifecycle is executed on the server (@this stands for the component triggering the request again). As the values you see for those attributes in the listing are the default values we don’t have to set them explicitly.

<h:commandButton id="toggle" actionListener="#{cc.toggle}">
  <f:ajax event="action" execute="@this"
      render="@this panel-content"/>

The following listing shows the complete composite component collapsiblePanel with ajax behavior.

<cc:interface componentType="at.jsflive.CollapsiblePanel">
  <cc:attribute name="collapsed"/>
  <cc:actionSource name="toggle"/>
  <cc:facet name="header"/>
  <h:panelGroup layout="block" styleClass="collapsiblePanel-header">
    <h:commandButton id="toggle" actionListener="#{cc.toggle}"
            ? 'jsflive:plus.png' : 'jsflive:minus.png']}">
      <f:ajax render="@this panel-content"/>
    <cc:renderFacet name="header"/>
  <h:panelGroup id="panel-content" layout="block">
    <h:panelGroup rendered="#{!cc.collapsed}">
  <h:outputStylesheet library="jsflive" name="components.css"/>

That’s it! The rest of the example was not changed for the ajax integration.

Tools like Firebug or the Chrome Developer Tools allow to check the type and contents of requests and responses. This way it is easy to determine that JSF now really sends ajax requests. You could further check what happens if the f:ajax tag is removed again (a classic JSF request will be sent).

For simplicity’s sake the source code for the presented example is based on collapsiblePanel02 and not collapsiblePanel03. It can be found in the Github repository collapsible04.


One response to “Ajaxify composite component collapsiblePanel

  1. Pingback: JSF 2.2: Configurable resource directory | JSFlive: Michael Kurz's JSF Weblog

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 )

Google+ photo

You are commenting using your Google+ 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 )


Connecting to %s