我正在尝试在JSF中显示一个树而不对我要显示的树的深度进行硬编码。也许对于一种配置我只想显示叶子,也许对于另一种配置我想要显示由它们上面的节点分组的叶子等等。所以对于一种配置,它可能是:
对于另一种配置,相同的底层数据结构可能会产生:
的
使用假设的第三种配置按超级类别等分组类别
我尝试制作一个复合组件,如果节点有更多子节点,则会递归调用自身。我是通过<ui:fragment rendered="#{node.hasChildren}">
完成的,并且 - 惊喜! - 这导致无限循环和堆栈溢出。
该项目已经安装了PrimeFaces,因此我正在关注PrimeFaces Tree
和TreeNode
。但那感觉不对;我不希望树节点在用户界面中可扩展。我希望一切都能完全扩展。我没有太深入这个兔子洞,所以我怀疑可能有一种方法可以通过Tree
实现这一点,但感觉我正在反对它的构建要做的事情。
这个问题的好处是什么?
<小时/> 编辑:我正在尝试使用&lt; tree&gt;和&lt; treeNode&gt;,但它不起作用。我的代码如下所示:
<p:tree value="#{cc.attrs.classification}" var="child">
<p:treeNode>
<ui:fragment rendered="#{child.childCount > 0}">
[do node stuff]
</ui:fragment>
<ui:fragment rendered="#{child.childCount == 0}">
[do leaf stuff]
</ui:fragment>
</p:treeNode>
</p:tree>
...其中classification
实现了TreeNode
接口。这会导致控制台出错,抱怨child
的类型为String,因此无法执行我要求的任何有趣的事情。我做错了什么?
答案 0 :(得分:4)
我尝试制作一个复合组件,如果节点有更多子节点,则会递归调用自身。我这样做了 - 惊喜! - 这导致无限循环和堆栈溢出。
失败是因为在构建JSF组件树期间未评估rendered
属性,而是仅在生成HTML输出期间。您基本上需要JSTL <c:if>
而不是<some:component rendered>
。 It runs during building the JSF component tree,所以你最终无限包括复合本身。
该项目已经安装了PrimeFaces,所以我正在查看PrimeFaces Tree和TreeNode。但那感觉不对;我不希望树节点在用户界面中可扩展。我希望一切都能完全扩展。
JSF实用程序库OmniFaces具有您正在寻找的组件<o:tree>
。该组件本身不会生成任何HTML标记,因此您可以自由地按照自己的方式声明HTML / JSF标记,也可以用于特定的深度级别。
Here's the showcase example。请注意页面底部的链接,它们指向源代码,这可能是有用/有趣的学习练习。你在开发复合材料时可能最初的想法并不是那么简单(毕竟不是the right tool for the job)。
至于区分叶节点,<o:tree>
提供了如下可能性:
<o:tree value="#{bean.tree}" var="item" varNode="node">
<o:treeNode>
<o:treeNodeItem>
<ui:fragment rendered="#{not node.leaf}">
...
</ui:fragment>
<ui:fragment rendered="#{node.leaf}">
...
</ui:fragment>
<o:treeInsertChildren />
</o:treeNodeItem>
</o:treeNode>
</o:tree>
答案 1 :(得分:3)
好。由于您可以从ManagedBean管理树结构,因此您可以在Java中进行递归,只需渲染树。
上周我做到了。在prerenderview期间,我使用递归方法初始化树,例如:
<p:tree value="#{bean.tree}" var="node" selection="#{bean.property}" >
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
希望它有所帮助!