Tuesday, August 11, 2009

af:treeTable: getting at a clicked node


I was working with an af:treeTable and its accompanying tree binding. I wanted to click a node to open it (if that node had sub nodes) and then automatically do something with the data in that node. I did not want to have to click on a link in the tree to identify the node.

Here is what I came up with:

public void onDisclosure(DisclosureEvent disclosureEvent) {
CoreTreeTable cmt = (CoreTreeTable)disclosureEvent.getSource();
PathSet ps = cmt.getTreeState();
Set ks = ps.getKeySet();
// The key-set is the set of addresses of keys that are open.
// Clearing it closes all that are open.

List rwKey = (List)cmt.getRowKey();
// The row-key is the address of the row that was just disclosed/clicked.
// It is a list of Strings, which contain 0-based numbers.
int depth = 0;
for (Object o1 : rwKey) {
ArrayList pathToAdd = new ArrayList();
for (int i = 0; i < depth + 1; i++) {
// This for loop just added the address of the node clicked,
// to the set of "open" nodes. Along the way it also enters
// all the parent node addresses as well, creating a new
// array list to store the address for each ancestor as well as
// the node clicked.

// I want to get the node that was clicked. I should be able to
// use the row-key to traverse the tree model to get the node I want.
TreeModel lTreeModel = (TreeModel)cmt.getValue();
Object lRowData = null;
for (Object lRowKeyIndexObject : rwKey) {
// Can I assume I start out with the tree model looking at root
// node?
String lRowKeyIndexString = (String)lRowKeyIndexObject;
int lIndex = Integer.parseInt(lRowKeyIndexString);
if (lTreeModel.isRowAvailable(lIndex)) {
lRowData = lTreeModel.getRowData(lIndex);// JUCtrlHierNodeBinding
if (lTreeModel.isContainer()) {
// When the loop is over the tree model should be
// set to the level and row that was clicked.
// Also lRowData should be the row we care about...the
// clicked row.

// We do not have to reset. I think each request the tree model
// resets. Traversing the tree model does not affect the way
// the tree table renders or looks.

JUCtrlHierNodeBinding lNodeBinding = (JUCtrlHierNodeBinding)lRowData;
String lNodeContents = (String)lNodeBinding.getAttribute(1);
// Display the found node.

// Next experiment. Create binding in query
// and a field that allows you to set this binding.
// See if when you open a node if it affects any others nodes
// or not.


Mauricio said...

Thanks a lot dude. You save my life :-) I had to add to the isContainer condition the isContainerEmpty to avoid exceptions.

Michael A. Fons said...

Always glad to save a life ;-)

I appreciate you improving the code! That makes our world a better place, right?