ADF table component usually requires a tree binding definition in the PageDef file pointing to some iterator binding. For example a table rendering rows of some VEmp view object would require the following structure in the PageDef file:
In this post I'm going to show how we can create a tree binding definition and a corresponding iterator binding dynamically at runtime.
Let's consider a managed bean method returning a tree binding definition:
And getIterator method looks for the corresponding iterator binding and creates it if it doesn't exist yet:
The technique shown in this post can be easily used to build a declarative component responsible for browsing data of any view object passed to the component as an attribute.
That's it!
<executables> <iterator Binds="VEmp" RangeSize="25" DataControl="AppModuleDataControl" id="VEmpIterator"/> </executables> <bindings> <tree IterBinding="VEmpIterator" id="VEmp"> <nodeDefinition DefName="com.cs.blog.dyntreebindingdemo.model.VEmp" Name="VEmp0"> <AttrNames> <Item Value="EmployeeId"/> <Item Value="FirstName"/> <Item Value="LastName"/> <Item Value="Email"/> <Item Value="PhoneNumber"/> <Item Value="HireDate"/> <Item Value="JobId"/> <Item Value="Salary"/> <Item Value="CommissionPct"/> <Item Value="ManagerId"/> <Item Value="DepartmentId"/> <Item Value="CreatedBy"/> <Item Value="CreatedDate"/> <Item Value="ModifiedBy"/> <Item Value="ModifiedDate"/> <Item Value="ActionComment"/> <Item Value="CreatedBy1"/> </AttrNames> </nodeDefinition> </tree> </bindings>
In this post I'm going to show how we can create a tree binding definition and a corresponding iterator binding dynamically at runtime.
Let's consider a managed bean method returning a tree binding definition:
private static final String VO_NAME = "VEmp"; private static final String ITERATOR_NAME = "VEmpIterator"; private static final String TREE_NAME = "VEmp"; private static final String DATACONTROL_NAME = "AppModuleDataControl"; public JUCtrlHierBinding getTree() { DCBindingContainer dcb = getBindings(); //May be the VEmp tree binding is already created JUCtrlHierBinding chb = (JUCtrlHierBinding)dcb.findCtrlBinding(TREE_NAME); if (chb == null) { // if not //Looking for the VEmpIterator iterator JUIteratorBinding iter = (JUIteratorBinding)getIterator(ITERATOR_NAME, VO_NAME); //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(); initValues.put(JUCtrlHierDef.PNAME_TypeBindings, new JUCtrlHierTypeBinding[] { typeBinding }); hierDef.init(initValues); //Create a tree binding instance chb = (JUCtrlHierBinding)hierDef.createControlBinding(dcb); //Add the instance to the current binding container dcb.addControlBinding(TREE_NAME, chb); } return chb; }
And getIterator method looks for the corresponding iterator binding and creates it if it doesn't exist yet:
public DCIteratorBinding getIterator(String iteratorName, String voName) { DCBindingContainer dcb = getBindings(); //It could be created earlier DCIteratorBinding jub = dcb.findIteratorBinding(iteratorName); if (jub==null) {// if not //Create and init an iterator binding definition JUIteratorDef jid = new JUIteratorDef(iteratorName, null, voName, null, 25); HashMap initValues = new HashMap(); initValues.put(JUTags.DataControl , DATACONTROL_NAME); jid.init(initValues); //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; }The readonly table using our dynamic tree binding should look like this:
<af:table rows="#{DynTableBean.tree.rangeSize}" fetchSize="#{DynTableBean.tree.rangeSize}" emptyText="#{DynTableBean.tree.viewable ? 'No data to display.' : 'Access Denied.'}" var="row" rowBandingInterval="0" value="#{DynTableBean.tree.collectionModel}" selectedRowKeys="#{DynTableBean.tree.collectionModel.selectedRow}" selectionListener="#{DynTableBean.tree.collectionModel.makeCurrent}" rowSelection="single" id="dc_t1"> <af:forEach items="#{DynTableBean.tree.attributeDefs}" var="def"> <af:column headerText="#{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>
The technique shown in this post can be easily used to build a declarative component responsible for browsing data of any view object passed to the component as an attribute.
That's it!
Very Useful article. Thank you. I've been struggled out with this issue.
ReplyDeleteAs well as this, do you know for Updatable table usage which has LOV?
How to define a list binding and attach it to some column?
You can find an example of a dynamic LOV here:
Deletehttp://adfpractice-fedor.blogspot.com/2012/10/deep-dive-into-oracle-adf-advanced.html
Another way:
ReplyDeletehttp://stefanoba.blogspot.it/2013/11/attribute-binding-dynamically-created.html