1

I will not paste my beans and model classes because there is everything ok with code. Problem is that first loop (ui:repeat) in dashboard.xhtml works fine but second loop (c:forEach) in comments.xhtml is not working.

I tested that #{comment.listComments.size()} in comments.xhtml really returns greater than zero which means that the c:forEach loop HAVE TO go through comments at least one time but it does not happening.

Dashboard.xhtml

<h:dataTable id="commentout" value="#{messageBean.getComments(msg)}" var="com" rendered="#{not empty messageBean.getComments(msg)}">
    <h:column>
        <div>
            <b><i>#{com.owner.firstName} #{com.owner.lastName}:</i></b>
            <h:outputText value=" #{com}" />
            <h:commandLink style="margin: 0 0 0 10px; padding: 0;" styleClass="add_comment" value="Answer" action="#{commentBean.createCommentOnComment(com)}" />
        </div>

        <ui:repeat value="#{com.listComments}" var="comment" rendered="#{com.hasChildren}">
            <ui:include src="comments.xhtml" />
        </ui:repeat>
    </h:column>
</h:dataTable>

comments.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html">

    <div style="margin-left: 20px;">
        <div>
            <b><i>>#{comment.owner.firstName} #{comment.owner.lastName}:</i></b>
            <h:outputText value=" #{comment}" />
            <h:commandLink style="margin: 0 0 0 10px; padding: 0;" styleClass="add_comment" value="Answer" action="#{commentBean.createCommentOnComment(comment)}" />
        </div>

        <c:when test="#{comment.hasChildren}">
            #{comment.listComments.size()} <!-- Visual test for checking if it is really greater than zero -->
            <c:forEach items="#{comment.listComments}" var="comment">
                <ui:include src="comments.xhtml" />
            </c:forEach>
        </c:when>
    </div>
</ui:composition>

Visual Problem: enter image description here

OR

If someone has any better idea of recursion method then it also can be an correct answer...



UPDATE:

If I change the <c:forEach /> to <ui:repeat /> and instead of using </c:when> use "rendered" attribute, it stuck and gives me error "Overflow".

Why <ui:repeat /> with <ui:include /> in summary gives me Overflow error?

Toms Bugna
  • 502
  • 2
  • 10
  • 30
  • 1
    @BalusC already answered something about it, take a look! http://stackoverflow.com/questions/21697024/cforeach-inside-primefacese-g-ppanelgrid-inside-uirepeat – Pellizon Nov 26 '14 at 19:20
  • 1
    This was really complicated. That guide in Your link helped me but not exactly the same way it was written there. But at least it gave me 100% explanation why this problem appeared how could be possible to solve it. Thank You. – Toms Bugna Nov 26 '14 at 22:48

2 Answers2

0

Thanks to @BalusC, I got information for successful solution from this source: c:forEach inside primefaces(e.g. p:panelgrid) inside ui:repeat.

The code that I have got written dashboard.xhtml is only one part of all code. This part is inside two more dataTables. I don't know if dataTables also are connected with this problem but for less problems I changed them to <c:when>, <c:forEach> and simple <div> tags.

The problem solved at the moment when I changed all <ui:include> to <c:forEach> tags.

If You meet problem like I had, then here are the steps that You should do for reaching the solution:
1) Change all:

<h:dataTable value="#{messageBean.getComments(msg)}" var="com" rendered="#{not empty messageBean.getComments(msg)}">
    <h:column>
        <div>
        ...
        </div>
    </h:column>
</h:dataTable>

To:

<c:when test="#{not empty messageBean.getComments(msg)}">
    <c:forEach items="#{messageBean.getComments(msg)}" var="com">
        <div>
        ...
        </div>
    </c:forEach>
</c:when>


2) Change all:

<ui:repeat value="#{com.listComments}" var="comment" rendered="#{com.hasChildren}">
    <ui:include src="comments.xhtml" />
</ui:repeat>

To:

<c:when test="#{com.hasChildren}">
    <c:forEach items="#{com.listComments}" var="subComment">
        <ui:include src="comments.xhtml">
            <ui:param name="comment" value="#{subComment}" />
        </ui:include>
    </c:forEach>
</c:when>


3) Important or just Suggestion:
3.1) Split <ui:include> tag and put the <ui:param /> tag inside of it!
3.2) For <ui:include> tag use different "var" parameter than <ui:param /> tag's "name" parameter has (Example is described and can be seen in 2nd chapter).

Community
  • 1
  • 1
Toms Bugna
  • 502
  • 2
  • 10
  • 30
-1

Instead of <c:when test="#{comment.hasChildren}"> ... </c:when> use <ui:fragment rendered="#{comment.hasChildren}"> ... </ui:fragment> and instead of the inner <c:forEach /> use another <ui:repeat />. Browsing around the web or stackoverflow you can find some good articles explaining why mixing JSTL with Facelets leads to problems.

-- EDIT You must pass your comment as a parameter to your include file:

<ui:include src="comments.xhtml">
   <ui:param name="comment" value="#{comment}" />
</ui:include>
amedeo avogadro
  • 595
  • 2
  • 7
  • 14
  • I already tried this before.. It calls this error: "/comments.xhtml @9,49 value=" #{comment}" Could not Resolve Variable [Overflow]: comment". – Toms Bugna Nov 26 '14 at 14:47