Sunday, March 20, 2011

Region Interation Example 2 - Using ADF Drag And Drop Framework

Problem:
Imagine you have 2 regions, Department and Employee region and want to refresh/requery Employee region after dragging a Department row from the Department region to the Employee region.
This is where ADF's Drag and Drop Framework comes into picture.
The following images shows what I wanted to accomplish:




Constraint:
Emp and Dept tables are not related to each other so the data model is independent of one another.

Solution:

  1. Created two fragments, containing Dept and Emp tables.
  2. On the Dept table, dropped the 'Drag Source' tag from the Operations Component Pallette and specify the operation as COPY and descriminator and Dept.
  3. On the Emp table, drop the 'Drop Target' tag from the Operations Component Pallette and specify a bean method as the drop event listener ( code snippet is shown below ).
  4. For the 'Drop Target' tag, do specify java.lang.Object as the Flavor Class for the child dataFlavor tag, otherwise it will not work.
  5. Include them in their respectative task flows and drop them as regions on the final page.
Here is the code snippet of Department.jsff

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <af:table value="#{bindings.DeptVO1.collectionModel}" var="row"
            rows="#{bindings.DeptVO1.rangeSize}"
            emptyText="#{bindings.DeptVO1.viewable ? 'No data to display.' : 'Access Denied.'}"
            fetchSize="#{bindings.DeptVO1.rangeSize}" rowBandingInterval="0"
            selectedRowKeys="#{bindings.DeptVO1.collectionModel.selectedRow}"
            selectionListener="#{bindings.DeptVO1.collectionModel.makeCurrent}"
            rowSelection="single"
            binding="#{backingBeanScope.backing_Department.t1}" id="t1">
    <af:column sortProperty="DeptId" sortable="false"
               headerText="#{bindings.DeptVO1.hints.DeptId.label}" id="c2">
      <af:outputText value="#{row.DeptId}" id="ot2">
        <af:convertNumber groupingUsed="false"
                          pattern="#{bindings.DeptVO1.hints.DeptId.format}"/>
      </af:outputText>
    </af:column>
    <af:column sortProperty="DeptName" sortable="false"
               headerText="#{bindings.DeptVO1.hints.DeptName.label}" id="c1">
      <af:outputText value="#{row.DeptName}" id="ot1"/>
    </af:column>
    <af:dragSource actions="COPY" defaultAction="COPY" discriminant="Dept"/>
  </af:table>
  <!--oracle-jdev-comment:auto-binding-backing-bean-name:backing_Department-->
</jsp:root>

And here is the code snippet of Employee.jsff

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <af:table value="#{bindings.EmpVO1.collectionModel}" var="row"
            rows="#{bindings.EmpVO1.rangeSize}"
            emptyText="#{bindings.EmpVO1.viewable ? 'No data to display.' : 'Access Denied.'}"
            fetchSize="#{bindings.EmpVO1.rangeSize}" rowBandingInterval="0"
            selectedRowKeys="#{bindings.EmpVO1.collectionModel.selectedRow}"
            selectionListener="#{bindings.EmpVO1.collectionModel.makeCurrent}"
            rowSelection="single"
            binding="#{backingBeanScope.backing_Employee.t2}" id="t2">
    <af:column sortProperty="EmpId" sortable="false"
               headerText="#{bindings.EmpVO1.hints.EmpId.label}" id="c3">
      <af:outputText value="#{row.EmpId}" id="ot3">
        <af:convertNumber groupingUsed="false"
                          pattern="#{bindings.EmpVO1.hints.EmpId.format}"/>
      </af:outputText>
    </af:column>
    <af:column sortProperty="EmpName" sortable="false"
               headerText="#{bindings.EmpVO1.hints.EmpName.label}" id="c2">
      <af:outputText value="#{row.EmpName}" id="ot2"/>
    </af:column>
    <af:column sortProperty="DeptId" sortable="false"
               headerText="#{bindings.EmpVO1.hints.DeptId.label}" id="c1">
      <af:outputText value="#{row.DeptId}" id="ot1">
        <af:convertNumber groupingUsed="false"
                          pattern="#{bindings.EmpVO1.hints.DeptId.format}"/>
      </af:outputText>
    </af:column>
    <af:dropTarget dropListener="#{backingBeanScope.backing_Employee.handleDrop}"
                   actions="COPY">
      <af:dataFlavor flavorClass="java.lang.Object"/>
    </af:dropTarget>
  </af:table>
  <!--oracle-jdev-comment:auto-binding-backing-bean-name:backing_Employee-->
</jsp:root>

And here is the code for the Managed Bean that contains the handleDrop drop listener method:

package view.backing;
import java.util.Iterator;
import java.util.List;
import javax.faces.component.UIComponent;

import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.view.rich.component.rich.data.RichTable;
import oracle.adf.view.rich.datatransfer.DataFlavor;
import oracle.adf.view.rich.datatransfer.Transferable;
import oracle.adf.view.rich.dnd.DnDAction;
import oracle.adf.view.rich.event.DropEvent;

import oracle.binding.BindingContainer;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;
import oracle.jbo.uicli.binding.JUCtrlHierBinding;
import oracle.jbo.uicli.binding.JUCtrlHierNodeBinding;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.RowKeySet;
public class Employee {
    private RichTable t2;
    public void setT2(RichTable t1) {
        this.t2 = t1;
    }
    public RichTable getT2() {
        return t2;
    }
   
  public DnDAction handleDrop(DropEvent dropEvent){
    Transferable transferable = dropEvent.getTransferable();
    DataFlavor<RowKeySet> rowKeySetFlavor = DataFlavor.getDataFlavor(RowKeySet.class, "Dept");
    RowKeySet rowKeySet = transferable.getData(rowKeySetFlavor);
    if (rowKeySet != null){
      CollectionModel dragModel = null;
      dragModel = transferable.getData(CollectionModel.class);
      if (dragModel!=null) {
        JUCtrlHierBinding binding = null;
        binding = (JUCtrlHierBinding) dragModel.getWrappedData();
        Iterator rowKeySetIterator = rowKeySet.iterator();
        if (binding != null) {
          if (rowKeySetIterator.hasNext()) {
            List rowKey = (List) rowKeySetIterator.next();
            JUCtrlHierNodeBinding nodeBinding = null;
            nodeBinding = binding.findNodeByKeyPath(rowKey);
            Row rw = nodeBinding.getRow();
            queryEmployees( ((oracle.jbo.domain.Number)rw.getAttribute("DeptId")).toString(), dropEvent.getDropComponent());
          }
          return DnDAction.MOVE;
        }
      }
    }
    return DnDAction.MOVE;
  }
  private void queryEmployees(String departmentId, UIComponent dropComponent){
    BindingContext bctx = BindingContext.getCurrent();
    BindingContainer bindings = bctx.getCurrentBindingsEntry();
    DCIteratorBinding employeesIter = (DCIteratorBinding)bindings.get("EmpVO1Iterator");
    ViewObject vo = employeesIter.getViewObject();
    vo.setWhereClause("dept_id = :TheDeptId");
    vo.defineNamedWhereClauseParam("TheDeptId", null, null);
    vo.setNamedWhereClauseParam("TheDeptId", departmentId);
    vo.executeQuery();
  }   
}

Thats it.

JDev Release 11.1.1.4

No comments:

Post a Comment