0
votes

I have a collection of items which each have a min, likely, and max value. There are validators to ensure the maximum is greater than the minimum etc. The validators use bindings so they can compare all three values the user has entered. Originally they were in a ui:repeat, but that was causing trouble with a dropdown and I found switching to a c:forEach fixed it. Unfortunately, it's also messed up the bindings. I'm hoping there's a way to fix them without going back to the ui:repeat.

Is it possible to have a binding in a c:forEach? Is there some way to add an id or a varStatus index to the binding so it isn't the same for every item in the list? e.g. in the example below I've tried things like

<h:inputText id="impactMin_#{impact.id}" binding="#{impactMin_#{impact.id}}">
<h:inputText id="impactMin_#{impact.id}" binding="#{impactMin}_#{impact.id}">

but unsurprisingly, those don't work. If anyone knows a sensible way of doing this, I'd be very grateful to hear it.

This is a simplified version of the code:

<c:forEach id="impacts" var="impact" items="#{mybean.impacts}" varStatus="i">
    <h:panelGroup layout="block" id="impactContainer_#{impact.id}">
        <h:outputText value="#{impact.score_impact_type_idInterface.score_impact_type_name}"/>
        <h:panelGroup layout="block" class="row form-group" id="impactAssessment_#{impact.id}">
            <h:panelGroup layout="block">
                <h:inputText id="impactMin" value="#{impact.current_impact_min}" binding="#{impactMin}" label="Minimum">
                    <f:attribute name="impactMl" value="#{impactMl}"/>
                    <f:attribute name="impactMax" value="#{impactMax}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactMinValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <h:panelGroup layout="block">
                <h:inputText id="impactMl" value="#{impact.current_impact_ml}" binding="#{impactMl}" label="Most likely">
                    <f:attribute name="impactMin" value="#{impactMin}"/>
                    <f:attribute name="impactMax" value="#{impactMax}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactLikelyValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <h:panelGroup layout="block">
                <h:inputText id="impactMax" value="#{impact.current_impact_max}" binding="#{impactMax}" label="Maximum">
                    <f:attribute name="impactMin" value="#{impactMin}"/>
                    <f:attribute name="impactMl" value="#{impactMl}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactMaxValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <div class="col-sm-12">
                <h:message for="impactMin"/> 
                <h:message for="impactMl"/>
                <h:message for="impactMax"/>
            </div>
        </h:panelGroup>
    </h:panelGroup>
</c:forEach>
1

1 Answers

0
votes

While trying to get a better understanding of bindings in general, I found this answer JSF 2 composites and binding for validation . While not quite the same thing, I found it could be adapted to a c:forEach like this:

<c:forEach id="impacts" var="impact" items="#{mybean.impacts}" varStatus="i">
    <h:panelGroup layout="block" id="impactContainer_#{impact.id}">
        <h:outputText value="#{impact.score_impact_type_idInterface.score_impact_type_name}"/>
        <h:panelGroup layout="block" class="row form-group" id="impactAssessment_#{impact.id}">
            <ui:param name="impactMin" value="impactMin_#{impact.id}" />
            <ui:param name="impactMl" value="impactMl_#{impact.id}" />
            <ui:param name="impactMax" value="impactMax_#{impact.id}" />
            <h:panelGroup layout="block">
                <h:inputText id="impactMin_#{impact.id}" value="#{impact.current_impact_min}" binding="#{requestScope[impactMin]}" label="Minimum">
                    <f:attribute name="impactMl" value="#{requestScope[impactMl]}"/>
                    <f:attribute name="impactMax" value="#{requestScope[impactMax]}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactMinValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <h:panelGroup layout="block">
                <h:inputText id="impactMl_#{impact.id}" value="#{impact.current_impact_ml}" binding="#{requestScope[impactMl]}" label="Most likely">
                    <f:attribute name="impactMin" value="#{requestScope[impactMin]}"/>
                    <f:attribute name="impactMax" value="#{requestScope[impactMax]}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactLikelyValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <h:panelGroup layout="block">
                <h:inputText id="impactMax_#{impact.id}" value="#{impact.current_impact_max}" binding="#{requestScope[impactMax]}" label="Maximum">
                    <f:attribute name="impactMin" value="#{requestScope[impactMin]}"/>
                    <f:attribute name="impactMl" value="#{requestScope[impactMl]}"/>
                    <f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
                    <f:validator binding="#{impactMaxValidator}"/>
                </h:inputText>
            </h:panelGroup>
            <div class="col-sm-12">
                <h:message for="impactMin_#{impact.id}"/> 
                <h:message for="impactMl_#{impact.id}"/>
                <h:message for="impactMax_#{impact.id}"/>
            </div>
        </h:panelGroup>
    </h:panelGroup>
</c:forEach>

Note the ui:param bits near the top. That seems to do the trick. Thanks BalusC!