Jakarta ee Primefaces 3.4:树selectedNode为空

Jakarta ee Primefaces 3.4:树selectedNode为空,jakarta-ee,jsf-2,primefaces,Jakarta Ee,Jsf 2,Primefaces,我是Primefaces的新手,我尝试使用Primefaces树已经好几天了。 基本上,我有一棵树。我在这棵树上附加了一个上下文菜单。单击上下文菜单时,将打开一个对话框窗口,显示有关树的选定节点的更多详细信息。我试图根据树和树表示例重现primefaces showcase 运行项目时,我试图打开对话框窗口,调试器中出现以下错误: WARNING: /protected/treeonly.xhtml @34,91 value="#{folderManagedBean.selectedNode.d

我是Primefaces的新手,我尝试使用Primefaces树已经好几天了。 基本上,我有一棵树。我在这棵树上附加了一个上下文菜单。单击上下文菜单时,将打开一个对话框窗口,显示有关树的选定节点的更多详细信息。我试图根据树和树表示例重现primefaces showcase

运行项目时,我试图打开对话框窗口,调试器中出现以下错误:

WARNING: /protected/treeonly.xhtml @34,91 value="#{folderManagedBean.selectedNode.data.name}": Target Unreachable, 'null' returned null
javax.el.PropertyNotFoundException: /protected/treeonly.xhtml @34,91 value="#{folderManagedBean.selectedNode.data.name}": Target Unreachable, 'null' returned null
请在下面的JSF页面中找到

    <?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>

        <h:form id="form">  

            <!--*********** Context Menu ***********-->
            <p:contextMenu for="folderTree">  
                <p:menuitem value="Rename Folder" update="folderPanel" oncomplete="folderDialog.show();" icon="ui-icon-plus"/>
            </p:contextMenu> 

            <!--*********** Folder Tree ***********-->
            <p:tree style="border:none;" id="folderTree" value="#{folderManagedBean.root}" var="folder" selectionMode="single" selection="#{folderManagedBean.selectedNode}">  
                <p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">  
                    <h:outputText value="#{folder.name}" />  
                </p:treeNode>  
            </p:tree>  


            <!--*********** Dialog Box ***********-->
            <p:dialog header="New Folder" widgetVar="folderDialog" modal="true" resizable="false"  
                      showEffect="clip" hideEffect="fold">  
                <p:outputPanel id="folderPanel">  
                    <h:panelGrid columns="2" cellpadding="4">  
                        <h:outputText value="Folder Name:" />  
                        <p:inputText value="#{folderManagedBean.selectedNode.data.name}"/> 
                    </h:panelGrid>  
                </p:outputPanel>
            </p:dialog>  


        </h:form>


    </h:body>
</html>

非常感谢您的帮助。

我希望页面加载时会出现异常。该对话框有一个inputText,它指向
selectedNode
。页面加载时该值为null(因为尚未进行选择),因此出现
NullPointerException
。您的问题有多种解决方案

最简单的解决方案是设置
好的,我终于解决了。
我将属性
appendToBody=“true”
添加到对话框中,它就工作了。属性
dynamic=“true”
不是必需的


更新:此解决方案可行,但不太清楚。我不清楚属性
appendToBody=“true”
的确切用途。这就是为什么,在我看来,上述解决方案更为正确。

请不要发布所有代码。只发布相关部分,不相关的部分会影响可读性,一点帮助都没有。你当然是对的。但我花了这么多天寻找解决方案,以至于我不再知道什么是相关的或不相关的。谢谢你的评论。我尝试添加dynamic=“true”。它可以工作,但仅在第一次显示该对话框时有效。其他时候,它只是保留以前的值。@CédricChristinaz您需要在选择发生后更新对话框。查看PrimeFaces的更新属性;-)否,页面加载时不显示异常。当单击树的节点时会显示异常。我已经使用上下文菜单中的“更新”属性来更新对话框。是否有必要在其他地方使用它?@CédricChristinaz是的,当前使用的更新将不起作用,因为更新在onComplete之后被触发(如果我错了,请纠正我)。查看我的更新答案,了解如何正确选择更新;-)我不会投反对票,因为这似乎有点苛刻,但不要为此使用
appendToBody
。正如PrimeFaces手册所述:
请小心使用appendToBody,因为页面定义和html dom会有所不同,例如,如果对话框位于h:form组件内且appendToBody已启用,则浏览器上的对话框将位于表单之外,并可能导致意外结果。在这种情况下,将表单嵌套在对话框中。
。相反,看看我的答案,老实说,这可能是你最好的解决办法。
@ManagedBean
@SessionScoped
public class FolderManagedBean implements Serializable{

    @EJB
    private FolderBean folderBean;

    private Folder froot;  
    private TreeNode root;

    private TreeNode selectedNode;  

    public FolderManagedBean() {   
    }

    @PostConstruct
    public void initialize(){
        root = buildTree();
    }

    public TreeNode getRoot(){
        return root;
    }


    private TreeNode buildTree(){
        froot = folderBean.getRootFolder();

        root = new DefaultTreeNode("root", null);      
        TreeNode realRoot = new DefaultTreeNode(froot, root);

        for (Folder child : froot.getChildFolders()){
            TreeNode tnChild = new DefaultTreeNode(child, realRoot);
            tnChild.setParent(realRoot);
            buildTreeRecursively(tnChild);
        }        
        return root;     
    }

    private void buildTreeRecursively(TreeNode currentNode){
        Folder folder =  (Folder)(currentNode.getData());
        for(Folder child : folder.getChildFolders()){
            TreeNode tnChild = new DefaultTreeNode(child, currentNode);
            tnChild.setParent(currentNode);

            buildTreeRecursively(tnChild);
        }
    }

    public TreeNode getSelectedNode() {
        return selectedNode;
    }

    public void setSelectedNode(TreeNode selectedNode) {
        this.selectedNode = selectedNode;
    }
}
<p:tree style="border:none;" id="folderTree" value="#{folderManagedBean.root}" var="folder" selectionMode="single" selection="#{folderManagedBean.selectedNode}">
    <p:ajax event="select" update="folderPanel"/>  
    <p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">  
        <h:outputText value="#{folder.name}" />  
    </p:treeNode>  
</p:tree>