How-to populate different select list content per table row

Posted by frank.nimphius on Oracle Blogs See other posts from Oracle Blogs or by frank.nimphius
Published on Thu, 23 Dec 2010 12:15:13 +0000 Indexed on 2010/12/23 12:56 UTC
Read the original article Hit count: 285

Filed under:

A frequent requirement posted on the OTN forum is to render cells of a table column using instances of af:selectOneChoices with each af:selectOneChoice instance showing different list values.

To implement this use case, the select list of the table column is populated dynamically from a managed bean for each row. The table's current rendered row object is accessible in the managed bean using the #{row} expression, where "row" is the value added to the table's var property.

<af:table var="row">
  ...
  <af:column ...>
    <af:selectOneChoice ...>
        <f:selectItems value="#{browseBean.items}"/>
    </af:selectOneChoice>
  </af:column
</af:table>

The browseBean managed bean referenced in the code snippet above has a setItems and getItems method defined that is accessible from EL using the #{browseBean.items} expression.

When the table renders, then the var property variable - the #{row} reference - is filled with the data object displayed in the current rendered table row.

The managed bean getItems method returns a List<SelectItem>, which is the model format expected by the f:selectItems tag to populate the af:selectOneChoice list.

public void setItems(ArrayList<SelectItem> items) {}
 
//this method is executed for each table row
public ArrayList<SelectItem> getItems() {
  FacesContext fctx = FacesContext.getCurrentInstance();   ELContext elctx = fctx.getELContext();   ExpressionFactory efactory =          fctx.getApplication().getExpressionFactory();          ValueExpression ve =          efactory.createValueExpression(elctx, "#{row}", Object.class);   
  Row rw = (Row) ve.getValue(elctx);       
 
//use one of the row attributes to determine which list to query and
 
//show in the current af:selectOneChoice list
 
// ...
 
ArrayList<SelectItem> alsi = new ArrayList<SelectItem>();
 
for( ... ){
     
SelectItem item = new SelectItem();
       
item.setLabel(...);
       
item.setValue(...);
       
alsi.add(item);
  
}
  
return alsi;
}

For better performance, the ADF Faces table stamps it data rows. Stamping means that the cell renderer component - af:selectOneChoice in this example - is instantiated once for the column and then repeatedly used to display the cell data for individual table rows. This however means that you cannot refresh a single select one choice component in a table to change its list values. Instead the whole table needs to be refreshed, rerunning the managed bean list query.

Be aware that having individual list values per table row is an expensive operation that should be used only on small tables for Business Services with low latency data fetching (e.g. ADF Business Components and EJB) and with server side caching strategies for the queried data (e.g. storing queried list data in a managed bean in session scope).

© Oracle Blogs or respective owner

Related posts about ADFv