组件在JSF中迭代和呈现嵌套的树状对象结构 [英] Component to iterate and render a nested tree-like object structure in JSF
问题描述
给定类定义如下:
public class注释{
String username;
String comment;
List< Comment>回复
// ...
}
使用构造一个JSF页面,它以如下的树形结构呈现 Comment
实例中包含的数据?
注释
UserOne说
blah blah
----
UserThree回复
blah blah blah
----
UserThree回答
blah blah blah
----
UserTwo说
blah blah
----
UserOne说
blah blah
如果嵌套只有一级深度,或者具有固定的最大深度,那么你可以嵌套JSF中继器组件,如< ui:repeat>
或< h:dataTable>
。
< ul>
< ui:repeat value =#{bean.comments}var =comment>
< li>#{comment.username}#{comment.comment}
< ul>
< ui:repeat value =#{comment.replies}var =reply>
< li>#{reply.username}#{reply.comment}< / li>
< / ui:repeat>
< / ul>
< / li>
< / ui:repeat>
< / ul>
但是如果嵌套级别是unlimited,那么你需要一个JSF组件,树层次。这在标准JSF组件集中不可用。您需要查看第三方组件库,如 PrimeFaces < p:tree>
或 RichFaces < rich:tree>
或 OmniFaces < o:tree>
。 OmniFaces一个允许你完全控制树标记,而对于其他人,你可能需要使用一些好的CSS来使它看起来像你想要的。
< o:tree value =#{bean.comments}var =comment>
< o:treeNode>
< ul>
< o:treeNodeItem>
< li>#{comment.username}#{comment.comment}
< o:treeInsertChildren />
< / li>
< / o:treeNodeItem>
< / ul>
< / o:treeNode>
< / o:tree>
为了清楚起见,我只能重命名 String comment
属性到消息
或文本
orso。
如果你已经在JSF 2.x,那么考虑< my:comments comment =#{bean.comments}>
复合组件,如下所示。
< cc:interface componentType =commentsComposite>
< cc:attribute name =commenttype =com.example.Commentrequired =true/>
< / cc:interface>
< cc:implementation>
< c:if test =#{not empty cc.comment.replies}>
< ul>
< c:forEach items =#{cc.comment.replies}var =commentvarStatus =loop>
< li>
#{comment.username}#{comment.comment}
< my:comments comment =#{cc.parent.comment.replies [loop.index]}/>
< / li>
< / c:forEach>
< / ul>
< / c:if>
< / cc:implementation>
@FacesComponent(commentsComposite)
public class CommentsComposite extends UINamingContainer {
private comment comment;
@Override
public void setValueExpression(String name,ValueExpression expression){
if(comment.equals(name)){
setComment expression.getValue(getFacesContext()。getELContext()));
}
else {
super.setValueExpression(name,expression);
}
}
public Comment getComment(){
return comment;
}
public void setComment(Comment comment){
this.comment = comment;
}
}
,复合组件的递归树。 p>
Given the class definition below:
public class Comment {
String username;
String comment;
List<Comment> replies;
// ...
}
Is it possible to use construct a JSF page which renders data contained in a Comment
instance in a tree like structure as follows?
Comments
UserOne said
blah blah
----
UserThree replied
blah blah blah
----
UserThree replied
blah blah blah
----
UserTwo said
blah blah
----
UserOne said
blah blah
If the nesting is only one level deep, or has a fixed amount of maximum depth, then you could just nest JSF repeater components like <ui:repeat>
or <h:dataTable>
in each other the usual way.
<ul>
<ui:repeat value="#{bean.comments}" var="comment">
<li>#{comment.username} #{comment.comment}
<ul>
<ui:repeat value="#{comment.replies}" var="reply">
<li>#{reply.username} #{reply.comment}</li>
</ui:repeat>
</ul>
</li>
</ui:repeat>
</ul>
But if the nesting level is "unlimited", then you need a JSF component instead which can render a tree hierarchy. This is not available in standard JSF component set. You'd need to look at 3rd party component libraries like PrimeFaces <p:tree>
, or RichFaces <rich:tree>
, or OmniFaces <o:tree>
. The OmniFaces one allows you to have full control over the tree markup, while for the others you'd possibly need to fiddle with some good CSS to get it to look like as you want.
<o:tree value="#{bean.comments}" var="comment">
<o:treeNode>
<ul>
<o:treeNodeItem>
<li>#{comment.username} #{comment.comment}
<o:treeInsertChildren />
</li>
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
I'd for clarity only rename String comment
property to message
or text
orso.
If you're already on JSF 2.x, then consider a <my:comments comment="#{bean.comments}">
composite component like below.
<cc:interface componentType="commentsComposite">
<cc:attribute name="comment" type="com.example.Comment" required="true" />
</cc:interface>
<cc:implementation>
<c:if test="#{not empty cc.comment.replies}">
<ul>
<c:forEach items="#{cc.comment.replies}" var="comment" varStatus="loop">
<li>
#{comment.username} #{comment.comment}
<my:comments comment="#{cc.parent.comment.replies[loop.index]}" />
</li>
</c:forEach>
</ul>
</c:if>
</cc:implementation>
@FacesComponent("commentsComposite")
public class CommentsComposite extends UINamingContainer {
private Comment comment;
@Override
public void setValueExpression(String name, ValueExpression expression) {
if ("comment".equals(name)) {
setComment((Comment) expression.getValue(getFacesContext().getELContext()));
}
else {
super.setValueExpression(name, expression);
}
}
public Comment getComment() {
return comment;
}
public void setComment(Comment comment) {
this.comment = comment;
}
}
See also the blog on the subject, recursive tree of composite components.
这篇关于组件在JSF中迭代和呈现嵌套的树状对象结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!