4 Replies Latest reply: Nov 18, 2011 10:06 AM by invincible_virus RSS

Mutiple ComboBoxes using c:forEach

invincible_virus Newbie

I want to create mutiple ComboBoxes from a Map containing label for the box as key and an object having [possible values, selected value] as Value (id=bundleItemDecoration).

This map is updated on value change of another ComboBox (id=bundleType).

Code works fine when rendered for the first time, but behaves wierd when re-rendered.

When I change the value in ComboBox (id=bundleType), Map is updated and labels (id=bundleItemDecoration) are displayed correctly on the Page but possible values in their corresponding ComboBoxes (id=bundleItemDecoration) are not changed.

Please help.

 

<s:decorate id="bundleTypeDecoration" template="../layout/edit.xhtml">
    <ui:define name="label">Bundle Type:</ui:define>

    <rich:comboBox id="bundleType" selectFirstOnUpdate="true"
        converter="#{bundleCodeConverter}"
        value="#{createBundle.bundleTypeSelectedCd}"
        defaultLabel="Select Bundle Type"
        required="true"
        suggestionValues="#{context.bundleCategoryList}"
        directInputSuggestions="true">

        <a4j:support event="onchange"
            action="#{bundleCategoryBillingDealList.setBillingDealRestrictions()}"
            reRender="billingInfoDecoration, bundleItemDecoration, billingDealRender, createBundleErrors"
            eventQueue="default" />

    </rich:comboBox>
</s:decorate>

<s:decorate id="bundleItemDecoration">

    <c:forEach var="bundleItem" items="#{createBundle.billingServIdDisplayNmSOList}">

        <s:decorate id="#{bundleItem.key}#{createBundle.bundleTypeSelectedCd}" template="../layout/edit.xhtml">
            <ui:define name="label">#{bundleItem.key}:</ui:define>
            <rich:comboBox
                selectFirstOnUpdate="true"
                value="#{bundleItem.value.selectedSOName}"
                defaultLabel="Select Service Offering"
                required="false"
                suggestionValues="#{bundleItem.value.soSuggestionList}"
                directInputSuggestions="true">

            </rich:comboBox>
        </s:decorate>

    </c:forEach>
</s:decorate>
  • 1. Re: Mutiple ComboBoxes using c:forEach
    Christian Peter Expert

    This is probably yet another buildtime vs. rendertime issue with c:forEach. Please try a4j:repeat or ui:repeat instead.

  • 2. Re: Mutiple ComboBoxes using c:forEach
    invincible_virus Newbie

    Got few links pointing to this buildtime vs rendertime issue - http://www.ninthavenue.com.au/blog/c:foreach-vs-ui:repeat-in-facelets

    Tried with a4j:repeat and ui:repeat, but the problem is even bigger with them.

    c:forEach works fine on first render but never updates on rerendering. But with a4j:repeat and ui:repeat comboboxes are not visible even on first time component rendering.

    BTW.. is 'rich:comboBox' buildtime or rendertime ?

  • 3. Re: Mutiple ComboBoxes using c:forEach
    Christian Peter Expert

    please try without the s:decorate and its constructed id and iterate with a4j:repeat or ui:repeat the rich:comboBox only:

     

    <a4j:outputPanel id="rerenderme">

     

    <a4j:repeat value="#{source}" var="item>

         <rich:comboBox .../>

    </a4j:repeat>

     

    </a4j:outputPanel>

     

    Then rerender the outputPanel instead of the s:decorate.

     

     

     

     

    I've tried in rf 3.3.3 and even this one works fine:

    <h:form>

         <s:decorate id="output1">

         <a4j:repeat value="#{demo.myList}" var="entry" rowKeyVar="ro">

              <s:decorate id="TEST#{ro}">

                   <rich:comboBox value="#{ro}"/>

              </s:decorate>

         </a4j:repeat>

    </s:decorate>

     

    buildtime vs. rendertime reflects here: the id TEST#{ro} is alwas "jid_xyz:j_id_abc:TEST" the #{ro} part is lost / evaluated to late.

     

    Maybe there is something wrong in your edit.xhtml template!

  • 4. Re: Mutiple ComboBoxes using c:forEach
    invincible_virus Newbie

    The issue is now solved. Rootcause was the usage of Map to hold the data.

    Combobox once rendered on the UI keeps refering to same data pointer e.g.

    suggestionValues="#{bundleItem.value.soSuggestionList}

    or

    suggestionValues="#{createBundle.billingServIdDisplayNmSOList.get(bundleItem.key).soSuggestionList}"

    will keep on pointing to the soSuggestionList of same key in the HashMap even if c:forEach has rerendered the UI component.

     

    Solution is to use List instead of map. On re-rendering the UI component, we will actually change the binding data to the suggestionValues property of rich:comboBox.

     

    Final working piece of code (with few more modifications) -

    <s:decorate id="billingDealRender">

        <h:panelGroup rendered="#{createBundle.showBillingDetails}">

            <div>

                <s:decorate id="billingDeal1" template="../layout/edit.xhtml">

                    <ui:define name="label">Billing Deal:</ui:define>

     

                    <rich:comboBox id="billingDeal" selectFirstOnUpdate="true"

                        converter="#{billingDealConverter}"

                        value="#{createBundle.bundleInfo.bundleBillingDealNm}"

                        defaultLabel="Select Billing Deal"

                        required="true"

                        suggestionValues="#{bundleCategoryBillingDealList.billingDealList}"

                        directInputSuggestions="true">

     

                    <a4j:support event="onselect" ajaxSingle="true"

                        reRender="billingDealRender"

                        eventQueue="default" />

                    </rich:comboBox>

                </s:decorate>

                <br class="clear" />

            </div>

        </h:panelGroup>

    </s:decorate>

     

    P.S. Thanks to Peter for the help.