0
votes

I have 3 entities - markets, topics and items. Markets is the parent of topics which is the parent of items. I'm hoping to find a simple way to invoke an action by selecting a value from the the final child node (items) and being taken to the page where the selected item can be viewed. The JSF:

 <p:tree value="#{treeTestBean.treeTest}" var="tree" 
                        dynamic="true" 
                        selectionMode="single" 
                        selection="#{treeTestBean.selectednode}">

                    <p:ajax event="select" listener="#{treeTestBean.onNodeSelect}"/>
                    <p:treeNode>
                        <h:outputText value="#{tree}"/>
                    </p:treeNode>
  </p:tree>  

The managed bean:

@Named(value = "treeTestBean")
@SessionScoped
public class TreeTestBean implements Serializable {

private TreeNode treetest;
private TreeNode selectednode;
private TreeNode node0;
private TreeNode node1;
private TreeNode node2;

private List<Enmarkets> markList;
private List<Entopic> topList;
private ListDataModel<Enitem> itList;

private Enitem selItem;

public TreeNode getTreeTest() {
    treetest = new DefaultTreeNode("Root", null);
    markList = rootFacade.findAll();

    for (Enmarkets m : markList) {

        node0 = new DefaultTreeNode(m.getMarketname(), treetest);
        int marketid = m.getMarketid();
        topList = topfac.marketTopNorm(marketid);

        for (Entopic t : topList) {
            node1 = new DefaultTreeNode(t.getTopicname(), node0);
            int topicid = t.getTopicid();
            itList = itfac.itemFroTopic(topicid);

            for (Enitem i : itList) {
                node2 = new DefaultTreeNode(i.getItemname(), node1);
            }

        }
    }

    return treetest;
}

The onNodeSelect method used in the ajax is also in the managed bean. If the selected node is a leaf it will search the item name and return that in the navigated page:

public void onNodeSelect(NodeSelectEvent event) {
this.setSelectednode(event.getTreeNode());

String somekey = selectednode.getRowKey();

if(selectednode.isLeaf()){
    String itemName = selectednode.getData().toString();

// Standard JPA call to search for item name here (omitted because this is not how i want to do it)

    FacesContext
            .getCurrentInstance()
            .getApplication()
            .getNavigationHandler()
            .handleNavigation(FacesContext.getCurrentInstance(), null, "/Main/Starter.xhtml?faces-redirect=true");
}
else {
    doNothing();
}
}

onNodeSelect is supposed to search the item name and navigates to the page with details of the selected item. The above method does this by searching for the Item name String and matching this to the name in a list of the item entity values created from the persistence layer. This will allow matching the selectednode String to the correct item name, so that the navigated jsf page is populated with the entity details (for example using a standard h:outputText tag). For several reasons, i prefer to search based on the entity ID instead of a String.

1
you actually READ the rowkey (but never use it!!!), why not also SET it with the entity ID? (Did you look at the api of the (Default)TreeNode?)Kukeltje
Thank you - very helpful!! No I didn't see the api that you provided.The one I saw was: primefaces.org/docs/api/5.0/org/primefaces/model/… which doesn't give much information at all. I mistakenly thought that the rowkey was linked to the entities. I will look into how to set the rowkey with entity ID.jay tai
I think you can also put the entity in there and implement a toString() for the display, but I'm not sureKukeltje
Both comments are extremely helpful and put me in the right direction . I will try both options and update the question. For the first one, setting the Row key, would you say it's necessary to make a Map of row keys and IDs, then pull the corresponding ID? I just want to find the most efficient way to do it. Thanksjay tai
I meant the entity as data in the treeNode, not as,a rowkey. And efficiency is relative, lots of quick clicks, them maybe store them ina session/viewscoped bean, use a second level cache etc… hard to sayaKukeltje

1 Answers

0
votes

Comments from Kukeltje greatly helped me in the right direction. First I include a Map(String, int) when creating the leaf node:

for (Enitem i : itList) {
node2 = new DefaultTreeNode(i.getItemname(), node1);
String rowK = node2.getRowKey();
int itid = i.getItemid();
rowMap.put(rowK, itid);

Then, in the onNodeSelect method I use this map to match the rowKey of the selectednode to the corresponding entity Id:

public void onNodeSelect(NodeSelectEvent event) {

if(selectednode.isLeaf()){
String rKey = selectednode.getRowKey();
if(rowMap.containsKey(rKey)) {
String xKey = rowMap.get(rKey).toString();
Integer rKeyint = Integer.parseInt(xKey);
selItem = itfac.find(rKeyint);

FacesContext
.getCurrentInstance()
.getApplication()
.getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "/Main/Client/ItemDetails.xhtml?faces-redirect=true");

    }
}
else {
doNothing();
}

This navigates to the page showing the detail of the selected node leaf. I suspect there might be an easier or more efficient way of doing this and would welcome any views. Like, I don't know if it's really necessary to make the string to integer conversions and I didn't think through a simpler way.

For now, this seems to solve my concrete problem. thanks