28 Feb 2013

Dynamic Table Declarative Component

In my previous post I created a tree binding definition with a correspondent iterator binding dynamically at runtime, and mentioned that this technique can be used to build a declarative component browsing data of any view object passed to the component as an attribute. In this post I'm going to show how we can do that.

The source code of our declarative component looks like this:
<af:componentDef componentVar="dyntable" var="attrs">
<af:xmlContent>   <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">     <attribute>       <attribute-name>ViewObjectName</attribute-name>       <required>true</required>     </attribute>     <attribute>       <attribute-name>RSIName</attribute-name>     </attribute>     <attribute>       <attribute-name>DataControlName</attribute-name>       <required>true</required>     </attribute>   </component> </af:xmlContent> <af:table rows="#{backingBeanScope.DynTableBean.tree.rangeSize}"           fetchSize="#{backingBeanScope.DynTableBean.tree.rangeSize}"           emptyText="#{backingBeanScope.DynTableBean.tree.viewable ?                        'No data to display.' : 'Access Denied.'}"           var="row" rowBandingInterval="0"           value="#{backingBeanScope.DynTableBean.tree.collectionModel}"           id="dc_t1">  <af:forEach items="#{backingBeanScope.DynTableBean.tree.attributeDefs}"              var="def">    <af:column headerText="#{backingBeanScope.DynTableBean.tree.labels[def.name]}"               sortable="true"               sortProperty="#{def.name}" id="dc_c1">      <af:outputText value="#{row[def.name]}" id="dc_ot1"/>    </af:column>  </af:forEach> </af:table> </af:componentDef>
The component has attributes for ViewObject name, VO's row set iterator name and data control name.  Have a note that we use a read-only dynamic table approach. Table's columns are going to be rendered dynamically by the forEach tag according to the VO's attributes and their UI hints.

Let's have a look at DynTableBean's code:

private static final String ITERATOR_NAME = "Iterator";
private static final String TREE_NAME = "TREE_";

public DCIteratorBinding getIterator(String iteratorName, String voName,
    String rsiName) {
    DCBindingContainer dcb = getBindings();
    DCIteratorBinding jub = dcb.findIteratorBinding(iteratorName);

    if (jub == null) {
        //Create and init an iterator binding definition
        JUIteratorDef jid =
                new JUIteratorDef(iteratorName, null, voName, rsiName, 25);
        HashMap initValues = new HashMap();
        initValues.put(JUTags.DataControl, getDataControlName());

        //Create an iterator binding instance
        jub = jid.createIterBinding(BindingContext.getCurrent(), dcb);

        //Add the instance to the current binding container
        dcb.addIteratorBinding(iteratorName, jub);
    return jub;


public JUCtrlHierBinding getTree() {
   DCBindingContainer dcb = getBindings();
   //May be the VEmp tree binding is already created
   JUCtrlHierBinding chb = 

    if (chb == null) { // if not
        //Looking for the VEmpIterator iterator
        JUIteratorBinding iter =
         (JUIteratorBinding)getIterator(getIteratorName(), getVOName(), 
       //Create and init a tree binding definition
        JUCtrlHierDef hierDef = new FacesCtrlHierDef();
        HashMap initValues = new HashMap();
        initValues.put(JUCtrlHierDef.PNAME_IterBinding, iter.getName());
        JUCtrlHierTypeBinding typeBinding = new JUCtrlHierTypeBinding();
                       new JUCtrlHierTypeBinding[] { typeBinding });

        //Create a tree binding instance
        chb = (JUCtrlHierBinding)hierDef.createControlBinding(dcb);

        //Add the instance to the current binding container
        dcb.addControlBinding(getTreeName(), chb);
    return chb;

//Generate a name of the tree bindning as "TREE_" + component's Id
//For example: TREE_dc1, TREE_dc2, ...
private String getTreeName() {
  return new StringBuilder(TREE_NAME).append(getID()).toString();

//Generate a name of the iterator bindning as "Iterator_" + component's Id
//For example: Iterator_dc1, Iterator_dc2, ...
private String getIteratorName() {
  return new StringBuilder(ITERATOR_NAME ).append(getID()).toString();         

//Getters for the component's attributes -
// ViewObjectName, RSIName, DataControlName, id
private String getVOName() {
  return (String) getMyself().getAttributes().get("ViewObjectName");     

private String getRSIName() {
  return (String) getMyself().getAttributes().get("RSIName");     

private String getDataControlName() {
  return (String) getMyself().getAttributes().get("DataControlName");     

private String getID() {
  return (String) getMyself().getAttributes().get("id");  

//A couple of helper methods to get an instance of our component
private RichDynamicDeclarativeComponent getMyself() {
    RichDynamicDeclarativeComponent _this =
    return _this;

private static Object getValueObject(String expr, Class returnType) {
    FacesContext fc = FacesContext.getCurrentInstance();
    ELContext elctx = fc.getELContext();
    ExpressionFactory elFactory = fc.getApplication().getExpressionFactory();
    ValueExpression valueExpr = 
       elFactory.createValueExpression(elctx, expr, returnType);
    return valueExpr.getValue(elctx);

And finally, let's use our declarative component. We're going to put on a page two tables browsing departments and employees:

    <af:form id="f1">
      <!--Browsing departments view object VDept -->
      <af:declarativeComponent viewId="DynTable.jsff" id="dc1"

      <!--Browsing employees view object VEmp -->
      <af:declarativeComponent viewId="DynTable.jsff" id="dc2"

That's it! The sample application for this post is available here. I used JDeveloper

1 comment:

  1. Thanks Eugene for the wonderful post.
    You are awesome as always !!!


Post Comment