5

I need dynamic number of columns. Richfaces supplies it with <rich:columns> in richfaces 3.3.3-final but for Richfaces 4 they seem to recommend <c:forEach>.

c:forEach

I can't get it to work properly.Since I can't depend on the var from the datatable I can't figure out how to feed <c:forEach> with the correct list of columns. (Each row has their own values but headers are the same)

Basically the data I want to display is a list with rows of x size, each row has a list of column values with y size. But how can have <c:forEach> tell the backing bean what row it's at so I can feed the correct columns?

ui/a4j:repeat

I dont want to reinvent the wheel because I need frozen columns and many other features. Creating the table html this way and use jQuery for other features have been considered. However this would be hopeless to maintain and to much work.

I also looked at constructing it from the backing bean creating children dynamically but I don't like that at all. This would have to be the last resort.

Using: Tomcat 7, servlet 3.0, JSF 2.1x - Mojarra, Richfaces 4.x

Update

Okay so I'm getting some results finally. However my headers don't show. The values show perfectly but not the headers. Some problem doing them with iteration or something perhaps?

    <rich:dataTable value="#{controller.rows}"
        var="row">
        <c:forEach items="#{controller.columns}" var="column">
            <rd:column id="name" width="250">
                <f:facet name="header">
                    <h:outputText value="#{row.myArrayList[column].header}" />
                </f:facet>
                <h:inputText value="#{row.myArrayList[column].value}"  disabled="#{row.myArrayList[column].open}"/>
            </rd:column>
        </c:forEach>
    </rich:dataTable>
Karl Kildén
  • 2,415
  • 22
  • 34

1 Answers1

7

The <c:forEach> is indeed best what you can get. The <ui/a4j:repeat> won't work as that runs during view render time while the UIData component really needs UIColumn children, not UIRepeat children.

In order to get the <c:forEach> to work, you need to supply it a list/map of all property names (and in case of a map maybe also header labels). Here's a concrete kickoff example assuming that Item has properties id, name and value and that #{bean.itemPropertyNames} returns a List<String> with exactly those property names.

<rich:dataTable value="#{bean.items}" var="item">
    <c:forEach items="#{bean.itemPropertyNames}" var="itemPropertyName">
        <rich:column>
            #{item[itemPropertyName]}
        </rich:column> 
    </c:forEach>
</rich:dataTable>

If you need to show column headers as well, then best is to have a Map<String, String> where the key represents the property name and the value represents the header value.

<rich:dataTable value="#{bean.items}" var="item">
    <c:forEach items="#{bean.itemProperties}" var="itemProperty">
        <rich:column>
            <f:facet name="header">#{itemProperty.value}</f:facet>
            #{item[itemProperty.key]}
        </rich:column> 
    </c:forEach>
</rich:dataTable>

Either way, the only disadvantage is that the #{bean} of <c:forEach items> can in this construct not be a view scoped one. It would be recreated on every request, unless you turn off partial state saving. It needs to be a request scoped one (or session or application). Note that it does not necessarily need to be the same bean as the one in <rich:dataTable value>.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • what you did is use #{item[itemPropertyName]} that's the missing puzzle piece I could never find. Basically my understanding of using parameters is that you use () not []? I will test this concept straight away – Karl Kildén Dec 12 '12 at 12:16
  • 1
    It does not represent a parameter, but a dynamic property name. See also "Brace notation" section of http://stackoverflow.com/tags/el/info – BalusC Dec 12 '12 at 12:17
  • 1
    What is ``? The `` must be an immediate child of the target component. So it has to be reattached to `` in case of a tagfile/custom component. – BalusC Dec 12 '12 at 13:00
  • Sorry I tried to change table to our own. No change when using rich:column. Hardcoded value works but not from the iteration. if I switch place with header and value I get opposite results so the data is there, just not displayed :( – Karl Kildén Dec 12 '12 at 13:07
  • 1
    Apparently the `` evaluates the header during view build time or something. To confirm it, use ``. If that "works", change the `#{controller.columns}` to be `Map` where the `K` is the property name and the `V` is the header value so that you can use `` and `` – BalusC Dec 12 '12 at 13:14
  • I can confirm that it worked using I will try your further suggestion right away! – Karl Kildén Dec 12 '12 at 13:16
  • very helpful comments. As usual thanks a lot it works great. Very interesting the part with the header. Was same behavior for h:datatable, rich:datatable and for our inhouse table. – Karl Kildén Dec 12 '12 at 13:42
  • can i use instead of h:outputText other components like graphic images wrapped in CommandLinks ? – Jalal Sordo Dec 25 '13 at 14:38