ADF 11g RichFaces – creating an alternative re-parent detail records using popup and drag & drop – assigning Employees to another Department in an intuitive way

Lucas Jellema
0 0
Read Time:5 Minute, 30 Second

The context: ADF 11g RichFaces. Reassigning details to another master can be done in several ways. One is through the Shuttle component, another using drag and drop in trees as my colleague Luc Bors demonstrated earlier on this blog. This article discusses yet another method, which involves showing details in a popup window and dragging them from that window to their new master record. Of course I will demonstrate this functionality using Employees and Departments.

In a previous article I demonstrated how you can create a master-table detail-table page for Departments and Employees. I then added a popup window to the page, to show the Employees for the currently selected Department. The popup window can be opened from a button in the table’s toolbar. When we navigate through the departments table, the popup window is synchronized.

We are going to build on top of that article and that application by adding functionality that allows the end user to select one or more Employees in the popup window and drag them to one of the Departments. By doing so, the Employees are reassigned to a new department, the model is updated and they will disàppear from the popup window they were dragged from.

Using just a few small steps leveraging the ADF 11g RichFaces drag & drop functionality, this can easily be done.

One question I have not yet solved: how can I determine what is shown during the drag operation? Right now I only get the primary key for the dragged Employee. I would like to show his picture, his name and job. But I have no clue as to how to do that.

Steps for implementing multi-row drag & drop

1. turn Employees table into a CollectionDragSource

   </af:column>
   <af:collectionDragSource modelName="emp"/>
</af:table> </af:panelWindow> </af:popup>

specify the model attribute – to connect to a specific drop target. Note that this is just a string that is used to tie source and target together – it does not refer to any bean or other object.

Specify that the table allows multi-row selection:

              <af:table partialTriggers="::DeptCollectionPanel:masterDetail1"
                        id="empTable" ...
                        rowSelection="multiple" width="746"
inlineStyle="height:164px;">

2. turn the Departments table into a CollectionDragTarget

                </af:column>
                <af:collectionDropTarget modelName="emp"/>
</af:table>

specify the same model as for the drag source

3. create a class with a method to handle the drop

public class TableDropHandler {
    public TableDropHandler() {
    }

    public DnDAction handleTableDrop(DropEvent dropEvent) {

        // dropSite will be null if dropped on the table but not on a row
        List<Key> serverRowKey = (List<Key>)dropEvent.getDropSite();
        Object stepNumber = "";
        Key dropRowKey = serverRowKey.get(0);
        DataFlavor<RowKeySet> df = DataFlavor.getDataFlavor(RowKeySet.class);
        RowKeySet droppedValue = dropEvent.getTransferable().getData(df);
        Object[] keys = droppedValue.toArray();
        oracle.jbo.domain.Number[] empKeys = new oracle.jbo.domain.Number[keys.length];
        // get the employee which we want to update the department
        for (int i = 0; i < keys.length; i++) {
              List list = (List)keys[i];
              empKeys[i] = (oracle.jbo.domain.Number)((Key)list.get(0)).getKeyValues()[0];
        }

        oracle.jbo.domain.Number newDeptno = (oracle.jbo.domain.Number)dropRowKey.getKeyValues()[0];
        return DnDAction.NONE;
    }
}

4. configure a managed bean based on this class

  <managed-bean>
    <managed-bean-name>DropHandler</managed-bean-name>
    <managed-bean-class>nl.amis.adf.TableDropHandler</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

5. configure the drop listener for the CollectionDragTarget – connect it to the bean

                </af:column>
                <af:collectionDropTarget dropListener="#{DropHandler.handleTableDrop}"
                                         modelName="emp"/>
              </af:table>

6. provide model level method for reassigning employees to a department

To handle the assignment in the model, I have created the following method on the HrmService Application Module implementation class. It takes an array of Number objects – the empno values for the employees to be reassigned. It then uses the AllEmployeesView usage to locate each and every employee and update their Deptno attribute with the deptno value passed as the second input parameter.

    public void reassignEmpToDept(oracle.jbo.domain.Number[] empKeys, oracle.jbo.domain.Number newDeptno) {
        for (int i=0;i<empKeys.length;i++) {
            Key empKey = new Key(new Object[]{empKeys[i]});
        EmpViewRowImpl empRow =
           (EmpViewRowImpl)this.getAllEmployees().getRow(empKey);
        empRow.setDeptno(newDeptno);
        }
    }

This method is published on the client interface of the HrmService and therefore becomes exposed on the Data Control palette.

7. Binding the reassign operation to the table

I have created an operation binding of this operation in the PageDefinition for my page.

    <methodAction id="reassignEmpToDept" RequiresUpdateModel="true"
                  Action="invokeMethod" MethodName="reassignEmpToDept"
                  IsViewObjectMethod="false" DataControl="HrmServiceDataControl"
                  InstanceName="HrmServiceDataControl.dataProvider">
      <NamedData NDName="empKeys" NDType="oracle.jbo.domain.Number[]"/>
      <NamedData NDName="newDeptno" NDType="oracle.jbo.domain.Number"/>
    </methodAction>
  </bindings>
</pageDefinition> 

In the DropListener method, I get hold of this operation binding, set its two parameters and invoke it. This will call the application module to update the employees selected during the drag & drop operation.

        ...
        BindingContext bcx =
            DCUtil.getBindingContext((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest());
        JUFormBinding bc = (JUFormBinding)bcx.getCurrentBindingsEntry();
        FacesCtrlActionBinding reassignOperationBinding =
            (FacesCtrlActionBinding)bc.findControlBinding("reassignEmpToDept");
        reassignOperationBinding.getParamsMap().put("newDeptno", newDeptno);
        reassignOperationBinding.getParamsMap().put("empKeys", empKeys);
        reassignOperationBinding.invoke();

Note: at this stage these changes are in the model, but not yet submitted to the database.

To see the reassign (multi-record drag & drop) in action, run the page.

Select two employee records and drag them:

When the mouse cursor hovers over a row in the Departments table, the row lights up – announcing itself as a drop target.

After the drop, the two employees are gone from the Department 20 popup window

When we select Department 40, we can verify in the popup Employees window that Employees have safely arrived in their destination department:


 

Resources

This great article by Luc Bors on our own AMIS Weblog on dragging & dropping in rich faces Trees: Dropping Trees.

A simple, quick introduction on Drag & Drop by Duncan Mills with useful comments by Don: http://groundside.com/blog/DuncanMills.php?p=574 .

Download the JDeveloper 11g Application for this article: hrmdragndrop.zip.

About Post Author

Lucas Jellema

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director and Oracle Developer Champion. Solution architect and developer on diverse areas including SQL, JavaScript, Kubernetes & Docker, Machine Learning, Java, SOA and microservices, events in various shapes and forms and many other things. Author of the Oracle Press book Oracle SOA Suite 12c Handbook. Frequent presenter on user groups and community events and conferences such as JavaOne, Oracle Code, CodeOne, NLJUG JFall and Oracle OpenWorld.
Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
Next Post

ADF 11g RichFaces - handling the client side double click to invoke a server side operation

  Selecting a row in a table with search results to drill down to its details is a fairly common operation in web application. I have implemented such functionality many times, in web applications based on JSP/TopLink, JSP/BC4J, JSF/Pojo, ADF 10g Faces/ADF BC. They are all similar, and they are […]
%d bloggers like this: