Вопрос по jsf – Компонент для итерации и рендеринга вложенной древовидной структуры объекта в JSF

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

Ваш Ответ

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>, Один 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>

I'd for clarity only rename String comment property to message or text orso.

Если вы уже используете 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;
    }

}

Смотрите также блог на эту тему,рекурсивное дерево составных компонентов.

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 со всеми комментариями в правильном порядке, а глубина атрибута - это глубина дерева комментариев (0 для базового уровня, 1 для дочерних элементов базового уровня, 2 для следующего и т. Д. ).

Теперь вы можете использовать пользовательский интерфейс: repeat для визуализации этого списка, используя свойство глубины для определения отступа.

Похожие вопросы