Monday, November 10, 2014

ADF : Programmatic access to View Accessor / Dependent LOV

View Accessor is often used to bring List of Values . In simple way , it is used to access a view object from another view object . why in the world should i need to access the view accessor programmatically when ADF View object has the privilege to handle it automatically.. well , thats a point.. There we have a use case //

In general,dependent LOV based on another attribute gets its value by executing view accessor.suppose i have an attribute whose view accessor is defined but the value which is required to be passed comes from various other action like previous page input. There is no view link between two view objects,no relationship .so its completely two independent view objects, but LOV in VO2 depends on VO1 input ..

In Vo2RowImpl :

//VA defined

 public RowSet getMoney() {
        return (RowSet)getAttributeInternal(MONEY);

//custom method
public Object executeViewAccessor(String val) {
      RowSet rs=(RowSet)getAttributeInternal(MONEY);
      rs.setNamedWhereClauseParam("str", str);
      return rs;

//Code to invoke the VA from AmImpl class. AM method is the bridge between two taskflow to pass parameters since we added TF2 as region in main TF. you should add the below AmImpl method as method action before PAGE 2 in TF2

AmImpl Method :

public void executeAction(String str) {
        ViewObjectImpl vo = this.getVo2();
        Row row = vo.createRow();
        VO2RowImpl rImpl = (VO2RowImpl )vo.getCurrentRow();


Now you have executed the View accessor of Money VO and your attribute in VO2 containing the LOV prepared based on the input being passed.

Note : There could be certainly many ways to achieve this functionality. This is one of the use case to explain ..

Sunday, November 9, 2014

ADF : Conditional Render in ADF Faces/ Manually creating ADF Table display

Use case :

The Employee of a company fills an online form of resigning reason before leaving the organization.
All these comments/reason submitted by various employees who left the organization will be saved in a separate DB table Job History.

Now the list of employees with the feedback  in the UI looks like this

Note: I am constructing these information as a table format without using ADF Table . The reason is to explain the scenario with more of real time case.

To achieve this we can use af:gridrow that can loop over the rows that the iterator has.

<af:iterator value="#{bindings.JobHistory.collectionModel}"    var="row" id="it2"   >
           //Code to loop over the rows


It just looks like the old jsp code where in the table TR and TD loops over a collection of data.
we generally fix the cell property of the row to fixed to have the limited alignment of the table in the page. The space between each row should be dynamic so that the text in the cells would not get overlapped.

something like this will makes sense

<af:iterator value="#{bindings.JobHistory.collectionModel}"    var="row" id="it2"   >
<af:gridRow id="gr3"height="#{row.comments gt 100 ? '40px' : '20px'}">
 <af:gridCell marginStart="10px" width="100px" id="gc7"       valign="stretch" halign="stretch">
              <af:outputText value="#{row.Name}" id="ot8" noWrap="false"/>
            <af:gridCell marginStart="10px" id="gc9" width="250px"   valign="stretch" halign="stretch">
              <af:outputText value="#{row.comments}" id="ot10"     inlineStyle="word-wrap:break-word" noWrap="false"/>

Also few more EL expressions for the conditional rendering of the ADF Faces components

<af:outputText value="#{ eq 'YES' and eq 'N' ? 'DONE': 'COMPLETED'}"  id="ot3"/>

 <af:outputText value="#{str}" id="ot1" rendered="#{requestContext.flag=='YES'}" />

<af:commandLink id="ci2"     rendered="#{row.flag == 'Y' }"  />