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????");
}
}
}
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????");
}
}
}