3

给定下面的类定义:

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
4

2 回答 2

3

如果嵌套只有一层深度,或者具有固定数量的最大深度,那么您可以像往常一样嵌套 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>

但是如果嵌套级别是“无限的”,那么您需要一个 JSF 组件来代替它来呈现树层次结构。这在标准 JSF 组件集中不可用。您需要查看PrimeFaces <p:tree>RichFaces <rich:tree>OmniFaces <o:tree>等 3rd 方组件库。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属性重命名为messageorso text

如果您已经在使用 JSF 2.x,那么请考虑如下所示的<my:comments comment="#{bean.comments}"> 复合组件。

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

}

另请参阅有关主题的博客,复合组件的递归树

于 2012-06-06T16:32:36.860 回答
0

您可以创建一个包装评论的新类。它将有一个注释和一个深度属性。

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 列表,所有评论都按正确的顺序排列,属性 depth 是评论树的深度(0 表示基本级别,1 表示基本级别的子级,2 表示下一个,等等。 )。

现在您可以使用 ui:repeat 来呈现此列表,使用 depth 属性来确定缩进。

于 2012-06-06T16:34:46.790 回答