4 Replies Latest reply on Sep 18, 2007 4:50 AM by denis.zjukow

    tags c:forEach and ui:repeat

      Hello,

      Having struggled for a couple of days I finally gave up and decided to ask for help.

      I use Seam with Facelets. What I want is to show a list of entities in a table cell i.e a single cell may contain a comma-separted list.

      Let's say I have two entity types: Item and Subitem. An instance of type Item may have a number of Subitems. In my case the relation between these two entity types is many-to-many.

      So if I have Item1 with three subitems: Subitem1, Subitem2 and Subitem3, I want to see something like this:

       <table>
      
       ...
      
       <tr>
      
       ...
      
       <td>Subitem1,SubItem2,Subitem3</td>
      
       ...
      
       </tr>
      
       ...
      
       </table>
      


      Please note that I don't want a comma after the last subitem in a cell (Subitem3 in this case). Nothing special, an obvious requierment, isn't it?

      The first thing I tried was ui:repeat:

       <!-- Table, each row represents an item. -->
       <h ataTable value="items" var="item">
      
       ...
      
       <!-- This is my tricky column. -->
       <h:column>
      
       <!-- I want to see all subitems in a single cell. -->
       <ui:repeat value="#{item.subitems}" var="subitem">
      
       <!-- Show a subitem. -->
       <h utputText value="#{item.subItems}" />
      
       <!-- Add separator. -->
       <h utputText value="," />
      
       </ui:repeat>
       <h:column>
      
       ...
      
       </h ataTable>
      


      Everything's fine except for the fact that there is a nasty comma after the last subitem. This made me try c:forEach tag:

       ...
      
       <!-- I want to see all subitems in a single cell. -->
       <c:forEach items="#{item.subitems}" var="subitem" varStatus="stat">
      
       <!-- Show a subitem. -->
       <h utputText value="#{item.subItems}" />
      
       <!-- Add separator for each subitem except for the last one. -->
       <c:if test="#{!stat.last}">
       <h utputText value="," />
       </c:if>
      
       </ui:repeat>
      
       ...
      


      Unfortunately this code won't work! It just leaves my favorite column empty. It seams that c:forEach do not see variable item.
      I then tried to find a way to add the conditional logic to ui:repeat, but haven't managed to find anything like c:forEach's 'varStatus'.

      Any ideas? Thank you all in advance!

        • 1. Re: tags c:forEach and ui:repeat

          c:forEach is build time tag. So it won't work in your case.
          (It is designed to iterate over components at UI tree build time, and not over data at render time)

          Why don't you put rendered condition on h:outputText which prints ",". You can get size of collection using EL function.

          Or better use t:dataList from tomahawk. It also has index variable.

          ui:repeat is buggy. RichFaces might also have some repeater tag.

          • 2. Re: tags c:forEach and ui:repeat

            And one more suggestion. For performance reasons just to that
            string concatenation in Java code.

            In this case you do not need any of UI repeat.
            Write a getter on backing bean.

            (or EL function which takes item collection)

            • 3. Re: tags c:forEach and ui:repeat
              amitev

              Actually List .toString returns the objects comma-separated - [Subitem1,SubItem2,Subitem3] (you just have to cut the first and the last char)

              • 4. Re: tags c:forEach and ui:repeat

                Thank you mgrouch and amitev. I like the idea of conditional rendering. I think it suits perfectly in this case.

                Let me ask one more question. Do jstl tags work with Seam scopes such as CONVERSATION, for example. This is not a build-in Servlet API scope, is it? Lets take c:forEach, for example, how can it find a variable if it is not in one of PAGE, REQUEST, SESSION or APPLICATION scopes? Thanks.