UI Repeat varStatus not working in CompositeComponent
Asked Answered
R

1

2

I use JSF 2.0 (Apache myFaces) on WebSphere Application Server 8.

I have a bean which contains a list of charts (data for jquery HighCharts). For each chart I need some JSF components + one Highchart Wrapper written as CompositeCompoent (look here)

So I use the ui:repeat function of jsf 2 like this:

<?xml version="1.0" encoding="UTF-8" ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:hc="http://java.sun.com/jsf/composite/chartComponents"
    template="/template/mytemplate.xhtml">

    <ui:define name="content">
        
        
        <ui:repeat value="#{chartCtrl.charts }" var="chart" id="chartrepeat" varStatus="chartStatus">
                #{chartStatus.index }
                <h:form id="chartform_#{chartStatus.index }">

                    <!-- some jsf select stuff-->               
                </h:form>
            
                    #{chartStatus.index }
                    <hc:Chart title="Statistics" id="hcchart_#{chartStatus.index }"
                    <!-- here's the problem-->

                        <ui:repeat value="#{chart.series }" var="serie">
                            <hc:ChartSeries series="#{serie.data }" />
                        </ui:repeat>
                    </hc:Chart>
                    #{chartStatus.index }
            </p:panel>
        </ui:repeat>


        <h:outputScript library="js" name="highcharts.js" />
        <h:outputScript library="js/modules" name="exporting.js" />
        <h:outputScript library="js" name="jquery-1.9.1.min.js" target="head" />

    </ui:define>
</ui:composition>

The #{chartStatus.index } works every where but not in hc:Chart id="". The generated js and div by this CC contains the id 'hcchart_chartdiv'. The index of the current repeat left.

How can I pass the correct number to the id attribute?

EDIT: Composite Component

Here is a part of the hc:Chart where the ID should be used

<cc:implementation>
    <div id="#{cc.id}_chartDiv" />

        <!-- Highcharts -_>
    <script type="text/javascript">
        $(function() {
            // Data must be defined WITHIN the function. This prevents
            // different charts using the same data variables.
            var options = {
                credits : {
                    enabled : false
                },
                chart : {
                    renderTo : '#{cc.id}_chartDiv',
            ....
        </script>

When I leave the attribute id in hc:Chart empty, then the generated ID is something like "j_id568185923_1_5f9521d0_chartDiv". But still without :row:.

EDIT 2: IndexOf Approach I tested another approach to set the ID of my chart.

id="hc_#{chartCtrl.charts.indexOf(chart) }"

I tried to use the IndexOf method of my ArrayList. I implemented HashCode und Equals method in all Classes. When I test it, it works fine. But when I use it with EL I get -1 returned.

Solution Just as BalusC said I cant use the ID tag for EL. So I simple created a new attribute in my CC. That works fine (just so easy).

Thanks BalusC.

Does someone has another idea?

Ruelas answered 27/2, 2013 at 14:5 Comment(0)
C
5

The id attribute is evaluated during view build time. The <ui:repeat varStatus> is set during view render time which is after view build time. Essentially, you've the same problem as explained in detail here: JSTL in JSF2 Facelets... makes sense?

Any EL expression in the id attribute must be available during view build time. If you replace <ui:repeat> by <c:forEach> which runs during view build time, then the id must be properly set. An alternative is to just get rid of EL in those id attributes based on <ui:repeat varStatus>. JSF will already automatically suffix the IDs of <ui:repeat> child components with the row index.

Note that the <c:forEach> may have unforeseen side effects when used in combination with view scoped beans and partial state saving enabled. See the aforelinked answer for details.

Cocoa answered 27/2, 2013 at 14:15 Comment(2)
Thanks for your response. When I use c:forEach I get an outoufmemory excepsion (heap space). But I dont know why. In my case, the div, where the charts is rendered to does not get the :row: because its a hardcoded id. Do you another idea?Ruelas
Is it including recursively? You should use a tree component instead like <p:tree> or a markupless <o:tree>. Or just leverage the unique ID autogeneration to JSF by removing any EL from id attribute.Cocoa

© 2022 - 2024 — McMap. All rights reserved.