Tree node selection did not update with dynamic ui:include

UI Components for JSF
Post Reply
airwave209
Posts: 3
Joined: 24 May 2011, 06:37

24 May 2011, 07:03

Hi,

I'm experimenting using a navigation tree with a <p:layout /> and an <ui:include />, which I want to dynamically update the <ui:include /> when I click on a tree node.

The backing bean

Code: Select all

@SessionScoped
public class MenuTreeBean implements Serializable
{
	private static final long serialVersionUID = -1L;

	private final TreeNode root;

	private TreeNode selectedNode;

	public MenuTreeBean()
	{
		root = new DefaultTreeNode("root", null);

		CustomTreeNode aaRoot = new CustomTreeNode("welcome", "Widgets", root);

		new CustomTreeNode("1", "Editor", aaRoot);
		new CustomTreeNode("2", "Calendar", aaRoot);

		setSelectedNode(aaRoot);
	}

	public TreeNode getMenuTree()
	{
		return root;
	}

	public TreeNode getSelectedNode()
	{
		return selectedNode;
	}

	public void setSelectedNode(TreeNode selectedNode)
	{
		this.selectedNode = selectedNode;
		this.selectedNode.setSelected(true);
	}

	public void onTreeNodeClicked(NodeSelectEvent e)
	{
		setSelectedNode(e.getTreeNode());
	}
}
The CustomTreeNode above simple extends DefaultTreeNode to add one more attribute, name.

Code: Select all

public class CustomTreeNode extends DefaultTreeNode
{
	private String name;

	public CustomTreeNode(String name, Object value, TreeNode parent)
	{
		super(value, parent);
		this.name = name;
	}

	public String getName()
	{
		return name;
	}
}
Main layout

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.prime.com.tr/ui">
<f:view contentType="text/html">
<h:head>

</h:head>
<h:body>
<p:layout fullPage="true">
	<p:layoutUnit position="left" width="200" resizable="true" collapsible="true">
		<h:form>
			<p:tree expanded="true" nodeSelectListener="#{menutree.onTreeNodeClicked}" id="tree"
					value="#{menutree.menuTree}" var="node" update="test,tree"
					selection="#{menutree.selectedNode}" selectionMode="single">
				<p:treeNode>
					<h:outputText value="#{node}" />
				</p:treeNode>
			</p:tree>
		</h:form>
	</p:layoutUnit>
	<p:layoutUnit position="center" resizable="true" collapsible="false">
		<h:panelGroup id="test" layout="block">
			<ui:include src="${menutree.selectedNode.name}.xhtml" />
		</h:panelGroup>
	</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
Correspondingly, there are few more little pages, which contain nothing more than a Primefaces widget - or simply HTML.

The problem I have is
- when I click on the Editor node above, it gets selected and highlighted, and the <ui:include /> loads the page/chunk I requested
- when I click on the Calendar node above, it gets selected and highlighted, and the <ui:include /> loads the page/chunk I requested
- when I click back on the Editor node above, it did not get selected, but the <ui:include /> still loads the page/chunk I requested; the Calendar node was still highlighted

If I turn off the update attribute at <p:tree />, tree node selection and highlight is working as expected; except I miss the dynamic <ui:include /> which I needed.

I wonder if I missed anything? TIA.

Environment: OpenJDK 6.0, Primefaces 2.2 + Aristo theme, Mojarra 2.1.1-b04, Maven2 jetty-maven-plugin 7.4.0.v20110414 and Firefox 4

edit: CustomTreeNode

airwave209
Posts: 3
Joined: 24 May 2011, 06:37

24 May 2011, 17:17

On the way of sorting out the problem, I added a few logging lines to the MenuTreeBean.

As seen from above, Widgets is set to be selected initially. Then, when I clicked Editor, the sequence of the methods are

Code: Select all

2011/05/24 23:06:25 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Widgets
2011/05/24 23:06:25 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Widgets
2011/05/24 23:06:25 com.foo.bar.MenuTreeBean setSelectedNode
INFO: Selected: Editor
2011/05/24 23:06:25 com.foo.bar.MenuTreeBean onTreeNodeClicked
INFO: Clicked: Editor
2011/05/24 23:06:25 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Editor
And when I clicked Calendar, the sequence became

Code: Select all

2011/05/24 23:07:15 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Editor
2011/05/24 23:07:15 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Editor
2011/05/24 23:07:15 com.foo.bar.MenuTreeBean setSelectedNode
INFO: Selected: Editor
2011/05/24 23:07:15 com.foo.bar.MenuTreeBean onTreeNodeClicked
INFO: Clicked: Calendar
2011/05/24 23:07:15 com.foo.bar.MenuTreeBean getSelectedNode
INFO: Selected: Calendar
I'm clueless on why the two setSelectedNode() calls have different behaviours. Is it some problem to do with the JSF request cycle?

Please advice and thanks again.

airwave209
Posts: 3
Joined: 24 May 2011, 06:37

26 May 2011, 05:36

Finally I managed to figure out the problem and made a workaround on my own.

As said above, when I specify the update IDs to both the tree and the <h:panelGroup/>, the selected node won't get highlighted but stay at the last selected node.

After countless tries and errors, I managed to edit primefaces's original treeview.js to force the node to highlight.

Code: Select all

// ...other lines omitted
YAHOO.lang.extend(PrimeFaces.widget.TreeView, YAHOO.widget.TreeView, {
    handleNodeClick: function (a) {
        if (this.isSelectionEnabled()) {
            this.handleNodeSelection(a);
            if (this.cfg.hasSelectListener || this.cfg.update) {
                this.doNodeSelectRequest(a)
            }
        } else {
            a.node.focus()
        }
        //Force the node to highlight
        a.node.highlight()
        return false
    },
// ...other lines omitted
But before this gets fixed or a better solution is available officially, we can still workaround the problem by adding a Javascript function to the <p:tree /> 's onNodeClick handler, to force highlighting the clicked node.

Code: Select all

function highlightNode(e)
{
    e.node.highlight();
}

Code: Select all

<!-- other lines omitted -->
<p:tree expanded="true" nodeSelectListener="#{menutree.onTreeNodeClicked}" id="tree"
        value="#{menutree.menuTree}" var="node" update="test,tree" onNodeClick="highlightNode"
        selection="#{menutree.selectedNode}" selectionMode="single">
<!-- other lines omitted -->
Thank you.

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 31 guests