【问题标题】:Primefaces 3.4: Tree selectedNode is nullPrimefaces 3.4:树 selectedNode 为空
【发布时间】:2012-09-10 19:45:15
【问题描述】:

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

当我运行我的项目时,我尝试打开对话框窗口,我在调试器中有这个错误:

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>

这里是托管 bean:

@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;
    }
}

任何帮助将不胜感激。

【问题讨论】:

  • 请不要发布您的所有代码。只贴相关部分,不相关的部分影响可读性,根本没有帮助。
  • 你当然是对的。但是我一直在寻找一个解决方案,以至于我不再知道什么是相关的或不相关的。谢谢你的评论。

标签: jakarta-ee jsf-2 primefaces


【解决方案1】:

我希望在页面加载时出现异常。该对话框有一个 inputText 引用 selectedNode。该值在页面加载时为空(因为尚未发生选择),因此 NullPointerException.您的问题有多种解决方案。

最简单的解决方案是设置&lt;p:dialog dynamic="true"对话框,然后只有在访问对话框时才访问该属性。

更新:您还需要使用 AJAX 事件处理程序更新选择对话框。

<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>

需要删除上下文菜单中的update 属性。

【讨论】:

  • 我尝试添加 dynamic="true"。它可以工作,但只是第一次显示对话框。其他时候,它只保留以前的值。
  • @CédricChristinaz 您需要在选择发生后更新对话框。查看 PrimeFaces 的更新属性 ;-)
  • 不,页面加载时不显示异常。单击树的节点时会显示异常。
  • 我已经使用上下文菜单中的更新属性来更新对话框。有必要在别的地方使用吗?
  • @CédricChristinaz 是的,当前使用更新将不起作用,因为更新在 onComplete 之后触发(如果我错了,请纠正我)。有关如何正确更新选择的信息,请参阅我的更新答案;-)
【解决方案2】:

好的,我终于解决了。 我将属性appendToBody="true" 添加到对话框中,它可以工作。 dynamic="true" 属性不是必需的。

更新:此解决方案有效,但不是很清楚。我不明白属性appendToBody="true" 的确切用途是什么。这就是为什么,在我看来,上面的解决方案更正确。

【讨论】:

  • 我不会投反对票,因为这似乎有点苛刻,但不要为此使用appendToBody。正如 PrimeFaces 手册所述:Use appendToBody with care as the page definition and html dom would be different, for example if dialog is inside an h:form component and appendToBody is enabled, on the browser dialog would be outside of form and may cause unexpected results. In this case, nest a form inside a dialog.。相反,请查看我的回答,老实说这可能是您的最佳解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
相关资源
最近更新 更多