Wednesday, July 11, 2012

Showing next row as current row after deleting a row from the ADF TreeTable

Whenever you delete a row from ADF table (af:table) the next row will be shown as the current row. This behavior is observed by default in the adf table. But this is not the same case with the adf tree table. To show the next row as the current row after deleting a row in ADF tree table, we need to manually get the next node and show the next row as the current row.

I tried in different ways to achieve this but I couldn't. Finally posted in the ADF EMG group and Chris resolved the issue.

Thanks to Chris for helping me to resolve the issue. I thought of sharing this info and it will be useful to others.

Create an Employee-Department testcase and drop the DepartmentVO as an ADF tree table onto the jspx page. Create action bindings for the Deletes of both Dept, Emp inside the pageDef. Create a button to delete a row from the tree table and keep the below bean method inside the actionListener of the button.

public void delete(ActionEvent actionEvent) {
// Not efficient to declare these here, but code is more readible if we
// don't push these declarations to the code below
DCBindingContainer bindingContainer =
((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry());
FacesCtrlActionBinding deleteDeptBinding =
(FacesCtrlActionBinding)bindingContainer.findCtrlBinding("DeleteDept");
FacesCtrlActionBinding deleteEmpBinding =
(FacesCtrlActionBinding)bindingContainer.findCtrlBinding("DeleteEmp");

// Lots of code to fetch the current selected row. I haven't tested
// this code for multiple selection deletes.
RichTreeTable treeTable = this.getMyTable();
RowKeySet rks = treeTable.getSelectedRowKeys();
Iterator<Object> keys = rks.iterator();
while (keys.hasNext()) {
List key = (List)keys.next();
JUCtrlHierBinding treeBinding = null;
CollectionModel collectionModel =
(CollectionModel)treeTable.getValue();
treeBinding = (JUCtrlHierBinding)collectionModel.getWrappedData();
JUCtrlHierNodeBinding nodeBinding =
treeBinding.findNodeByKeyPath(key);

// Hurray we finally have the current selected row
Row row = nodeBinding.getRow();

// Are we deleting a department (level 0) or employee (level 1)?
String rowType = row.getStructureDef().getDefName();
if (rowType.equalsIgnoreCase("DepartmentsView")) {
deleteDeptBinding.execute();
// If you get db cascade delete errors when you delete, change
// the ADF BC entity association composition association
// properties to do this for you
AdfFacesContext.getCurrentInstance().addPartialTarget(treeTable);

} else if (rowType.equalsIgnoreCase("EmployeesView")) {

// If deleting an employee we need somewhere to set the current
// row after the delete. The parent gives us a handle to do this
JUCtrlHierNodeBinding parentNode = nodeBinding.getParent();
JUCtrlHierNodeBinding nextNode = null;

// If we're to call the DeleteEmp binding now we would get
// a "JBO-25039: No current row in row set iterator" error. As
// such we need to set the iterator's current row to that
// selected in the tree before we delete the row
DCIteratorBinding empIterator =
bindingContainer.findIteratorBinding("EmployeesView3Iterator");
Key currentEmpRowKey = row.getKey();
String rowKeyString = currentEmpRowKey.getAttribute(0).toString();
empIterator.setCurrentRowWithKeyValue(rowKeyString);

// Before deleting the employee record, we need to make a
// decision on what row to select after the current row. Choices:
// 1) The next sibling
// 2) The previous sibling as there is no next sibling
// 3) The parent assuming there are no siblings left
int currentRowIndex = empIterator.getRowSetIterator().getCurrentRowIndex();
if (empIterator.getRowSetIterator().hasNext()) {
nextNode = (JUCtrlHierNodeBinding)parentNode.getChildren().get(currentRowIndex +1);
} else if (empIterator.getRowSetIterator().hasPrevious()) {
nextNode = (JUCtrlHierNodeBinding)parentNode.getChildren().get(currentRowIndex -1);
} else {
nextNode = parentNode;
}

// Pow!
deleteEmpBinding.execute();

// Set the trees selected row to the keyPath of the nextNode
// we determined above.
//I didn't try setting the collectionModel in my actual usecase.
ArrayList nextNodeKeyList = nextNode.getKeyPath();
RowKeySet keyset = new RowKeySetImpl();
keyset.setCollectionModel((CollectionModel)(treeTable.getValue()));
keyset.add(nextNodeKeyList);
treeTable.setSelectedRowKeys(keyset);


AdfFacesContext.getCurrentInstance().addPartialTarget(treeTable);
} else {
System.out.println("Huh????");
}
}
}

Thursday, May 31, 2012

Exporting master-child data to CSV or Excel from a tree table


If you want to export the data from a treeTable that shows the master detail hierarchy, we can't use the af:exportCollectionActionListener. It exports only the master records data not the child record's data.

To export both master and child records data, I used af:fileDownloadActionListener to export/download the master-detail data in a CSV file. We can also export the same data to an excel file by using apache POI apis.

Steps followed:

1) Create the master-detail data model (Departments - Employee) in the application module.
2) Drag the DepartmentVO as the adf tree table onto a jspx page.
3) Create a command button (Export) and drop the component af:fileDownloadActionListener inside
    the Export button.




4) Write the below logic inside the bean method to add the data to the file.



5) When you run the page, click on the Export button. It will export the Departments-Employees data in the
     hierarchical way.









To export the data to excel instead of CSV, create another  button in the jspx as

      <af:commandButton text="ExportXLS" id="cb3" immediate="true">
          <af:fileDownloadActionListener filename="EmpDept.xls"
                                         method="#{backingBeanScope.TreeBean.exportDataToExcel}"
                                         contentType="application/vnd.ms-excel"/>
        </af:commandButton>


    private void addLabel(WritableSheet sheet, int column, int row, String s)
        throws WriteException, RowsExceededException {
      Label label;     
      label = new Label(column, row, s, timesBoldUnderline);
      sheet.addCell(label);
    }


 To export the data to the xls file, use below code inside your bean