鉴于下面的课程定义:
public class Comment {
String username;
String comment;
List<Comment> replies;
// ...
}
是否可以使用构造一个JSF页面,该页面在结构如树的结构中呈现Comment
实例中包含的数据,如下所示?
Comments
UserOne said
blah blah
----
UserThree replied
blah blah blah
----
UserThree replied
blah blah blah
----
UserTwo said
blah blah
----
UserOne said
blah blah
答案 0 :(得分:2)
如果嵌套只有一层深度,或者具有固定数量的最大深度,那么您可以通过常规方式将<ui:repeat>
或<h:dataTable>
之类的JSF转发器组件嵌套在一起。
<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>
但是如果嵌套级别是“无限制”,那么您需要一个可以呈现树层次结构的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
属性重命名为message
或text
orso。
如果您已使用JSF 2.x,请考虑下面的<my:comments comment="#{bean.comments}">
composite component。
<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;
}
}
另请参阅有关该主题的博客recursive tree of composite components。
答案 1 :(得分:0)
您可以创建一个包含Comment的新类。它会有一个注释加上一个深度属性。
public CommentWithDepth {
private Comment comment;
private int depth;
public CommentWithDepth(Comment comment, int depth) {
this.comment = comment;
this.depth = depth;
}
public Comment getComment() {
return comment;
}
public int getDepth() {
return depth;
}
}
然后创建一个CommentWithDepth列表,其中所有注释都按正确的顺序排列,属性深度是注释树的深度(0表示基本级别,1表示基础级别的子级,2表示下一个级别)等等。)。
现在你可以使用ui:repeat来渲染这个列表,使用depth属性来确定缩进。