Friday, March 5, 2010

JSF expanding row of data table

Problem :

To create a table from a list of objects obtained from DB in which each row has a button.On clicking the button the details of the row is displayed as next row.
This is not possible with JSF <h:dataTable>

Solution:

Use JSTL to iterate through the list and use plain html to create the table. 
Use jsf components inside the <td> of the table
Here is the sample code

 <table>  
 <tr class="colHdr">  
   <td >Column 1</td>  
   <td >Column 2</td>  
   <td >Column 3</td>  
   <td >Column 4</td>  
   <td >Column 5</td>  
 </tr>  
 <!-- use jstl1.2 for iterating the list of hardware objects-->  
 <c:forEach items="#{BackingBean.hardwareList}" var="hardware" varStatus="status">  
 <tr>  
   <td colspan="5" class="colStyle">  
     <h:outputText value="#{hardware.hardwareDesc}"/>  
   </td>  
 </tr>  
 <!--use status var to alter the row color -->  
 <tr class="${status.index % 2 == 0 ? 'style1' : 'style2'}">  
   <td> <!--use f:setPropertyActionListener to get which hardware's(row) detail button is clicked -->  
  <h:commandButton value="Hardware Details" action="#{BackingBean.details}">  
     f:setPropertyActionListener target="#{BackingBean.hardware}" value="#{hardware}" />  
  <!-- Backing bean must have getter and setter for hardware type -->  
  </h:commandButton>  
  </td>  
   <td><h:inputText size="4" value="#{hardware.col1}"/></td>  
   <td><h:inputText size="4" value="#{hardware.col2}"/></td>  
   <td><h:inputText size="4" value="#{hardware.col3}"/></td>  
   <td><h:inputText size="4" value="#{hardware.col4}"/></td>  
  <!-- this column is rendered only for hardware whose group is true-->  
   <td><h:inputText size="4" rendered="#{hardware.group}" value="#{hardware.col5}"/></td>  
 </tr>  
 <!-- On clicking the detail button set the showDetails   
 (of the corresponding hardware object obtained through the f:setPropertyActionListener)   
 to true in the backing bean -->  
 <h:panelGroup rendered="#{hardware.showDetails}">  
 <tr>  
 <td colspan="5">  
 <hr />  
 </td>  
 </tr>  
 <tr>  
   <td class="text1">Minimum</td>  
   <td class="text1"><h:outputText value="#{hardware.col1Min}"/></td>  
   <td class="text1"><h:outputText value="#{hardware.col2Min}"/></td>  
   <td class="text1"><h:outputText value="#{hardware.col3Min}"/></td>  
   <td class="text1"><h:outputText value="#{hardware.col4Min}"/></td>  
   <td class="text1"><h:outputText value="#{hardware.col5Min}"/></td>  
 </tr>  
 <tr>  
   <td class="genText">Optimal</td>  
   <td class="expLineAlt"><h:outputText value="#{hardware.col1Opt}"/></td>  
   <td class="expLineAlt"><h:outputText value="#{hardware.col2Opt}"/></td>  
   <td class="expLineAlt"><h:outputText value="#{hardware.col3Opt}"/></td>  
   <td class="expLineAlt"><h:outputText value="#{hardware.col4Opt}"/></td>  
   <td class="expLineAlt"><h:outputText value="#{hardware.col5Opt}"/></td>  
 </tr>  
 </h:panelGroup>  
 </c:forEach>  
 </table>  

Some useful links about customizing data table in JSF
expand-collapse-of-table-rows-in-datatable-jsf
Everything about data table in JSF

Followers