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

    Mutiple ComboBoxes using c:forEach

    invincible_virus

      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
          mcmurdosound

          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

            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
              mcmurdosound

              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

                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.