6 Replies Latest reply on Sep 18, 2007 9:00 AM by gatz

    Not all components reRendered

    gatz

      Hi All.
      I'm pretty new to RichFaces and also to JSF, but my fastest and only way to test some technology is to force myself to apply it to a new project :)
      I know the basics of ajax and implemented something from scratch in the past.

      Getting down to the problem, I have this couple of selectOneMenu components that are meant to customize a view, by realoding it through ajax calls.

      I have three components and a table, but only the table gets updated...
      The funny thing is. If I hard-refresh the page, the view gets refreshed and also the three components, since the bean has a session-scope, and from there on, I always see the fields changed that way. Like I had to hard-refresh every time.
      Looks like I'm skipping some JSF lifecycle step...

      Thanks in advance

      Here is the code.

      <f:view>
       <f:loadBundle basename="com.maserati.gtcc.messages" var="msg" />
       <rich:panel header="#{msg['priceconf.title']}">
       <h:form id="priceForm">
       <h:panelGrid>
       <h:messages />
       </h:panelGrid>
       <rich:panel>
       <h:panelGrid columns="2">
       <h:outputLabel value="#{msg['priceconf.market']}" for="selMarket" />
       <h:outputLabel value="#{msg['priceconf.model']}" for="selModel" />
       <h:selectOneMenu id="selMarket" value="#{priceconfBean.marketCode}">
       <a4j:support action="#{priceconfBean.updateDetail}" event="onchange" ajaxSingle="true" reRender="detail" />
       <f:selectItems value="#{priceconfBean.availableMarkets}" />
       </h:selectOneMenu>
       <h:selectOneMenu id="selModel" value="#{priceconfBean.modelCode}">
       <a4j:support action="#{priceconfBean.updateDetail}" event="onchange" ajaxSingle="true" reRender="detail" />
       <f:selectItems value="#{priceconfBean.availableModels}" />
       </h:selectOneMenu>
       </h:panelGrid>
       </rich:panel>
       <rich:spacer height="4" />
       <rich:panel>
       <a4j:outputPanel id="detail">
       <h:panelGrid columns="3">
       <h:outputLabel value="#{msg['priceconf.priceMask']}" for="selMask" />
       <h:outputLabel value="#{msg['priceconf.available']}" for="chkAvailable" />
       <h:outputText value="#{msg['priceconf.car.baseprice']}" />
       <h:selectOneMenu id="selMask" value="#{priceconfBean.priceMask}">
       <f:selectItems value="#{priceconfBean.priceMasks}" />
       </h:selectOneMenu>
       <h:selectBooleanCheckbox id="chkAvailable" value="#{priceconfBean.available}" />
       <h:inputText id="txtBasePrice" value="#{priceconfBean.basePrice}" />
       </h:panelGrid>
       <rich:spacer height="4" />
       <rich:dataTable id="tblDetailOpts" onRowMouseOver="this.style.backgroundColor='#F1F1F1'"
       onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'"
       cellpadding="0" cellspacing="0" width="700" border="0"
       value="#{priceconfBean.optList}" var="row">
       <rich:column>
       <h:outputText value="#{row[0]}" />
       </rich:column>
       <rich:column>
       <h:outputText value="#{row[1]}" />
       </rich:column>
       <rich:column>
       <h:outputText value="#{row[2]}" />
       </rich:column>
       <rich:column>
       <h:outputText value="#{row[3]}" />
       </rich:column>
       <rich:column>
       <h:outputText value="#{row[4]}" />
       </rich:column>
       </rich:dataTable>
       </a4j:outputPanel>
       </rich:panel>
       </h:form>
       </rich:panel>
      </f:view>
      

      public class PriceconfBean implements InitializingBean {
      
       protected final Log logger = LogFactory.getLog(getClass());
      
       private ConfigService configService;
      
       private HashMap<String, Integer> marketIds;
      
       private SelectItem[] availableMarkets;
       private SelectItem[] availableModels;
       private SelectItem[] priceMasks;
       private String marketCode;
       private String modelCode;
       private String priceMask;
       private Boolean available;
       private BigDecimal basePrice;
       private Collection optList;
      
       public void afterPropertiesSet() throws Exception {
       // get available markets
       ArrayList<SelectItem> items = new ArrayList<SelectItem>();
      
       marketIds = new HashMap<String, Integer>();
       Collection mkts = configService.getCountriesWithMarket();
       Iterator mktsIt = mkts.iterator();
       while (mktsIt.hasNext()) {
       Country c = (Country) mktsIt.next();
       SelectItem item = new SelectItem(c.getCodmercato(), c.getDescEn());
       marketIds.put(c.getCodmercato(), c.getId());
       items.add(item);
       }
      
       availableMarkets = (SelectItem[]) items.toArray(new SelectItem[items.size()]);
      
       // get available models
       SelectItem[] models = { new SelectItem("7398040", "GT42AU") };
       availableModels = models;
      
       // numeric masks
       SelectItem[] masks = { new SelectItem("", "-"), new SelectItem("#.##0,00", "1.234,56") };
       priceMasks = masks;
      
       // populate values
       marketCode = (String) availableMarkets[0].getValue();
       modelCode = (String) availableModels[0].getValue();
       updateDetail();
       }
      
       public String updateDetail() {
       optList = configService.getOptsByModelVersion(modelCode, marketCode);
       Country c = configService.getCountryById(marketIds.get(marketCode));
       priceMask = c.getPricemask();
       available = c.isAvailable();
       basePrice = configService.getCarPrice(modelCode, marketCode);
      
       return null;
       }
      
       public void setConfigService(ConfigService configService) {
       this.configService = configService;
       }
      
       public SelectItem[] getAvailableMarkets() {
       return availableMarkets;
       }
      
       public SelectItem[] getAvailableModels() {
       return availableModels;
       }
      
       public SelectItem[] getPriceMasks() {
       return priceMasks;
       }
      
       ...
      
      }
      


        • 1. Re: Not all components reRendered
          maksimkaszynski

          So you want to reRender entire a4j:outputpanel, but your
          h:selectOneMenu id="selMask" value="#{priceconfBean.priceMask}" and h:selectBooleanCheckbox id="chkAvailable" value="#{priceconfBean.available}" are not reRendered?

          • 2. Re: Not all components reRendered
            gatz

            Exactly!

            Also, if I take a look in the ajax replies, I notice that the state of those three controls is wrong (= hasn't changed), while the table is ok, so it has something to do with the request processing.

            • 3. Re: Not all components reRendered
              maksimkaszynski

              How those inputs are supposed to be changed?
              Code you attached gives no idea.
              If they are changed by user, and then re-rendered with their old values - remove ajaxSingle attribute from support components.

              • 4. Re: Not all components reRendered
                gatz

                OMG that is just crazy...

                I SWEAR I had tried that multiple times before, but nothing would happen, while now I removed it and it magically worked...

                It still does not make sense in my head, though. Why would I want to submit the whole bunch while I only do logic on the control that I just changed?

                Btw, all the logic is inside the method updateDetail().

                Thanks anyway ;)

                • 5. Re: Not all components reRendered
                  maksimkaszynski

                  That's simple. If component is set to be ajaxSingle, no other components get processed. So other selectMenus were neither detected, nor updated, and their old values were rendered.

                  • 6. Re: Not all components reRendered
                    gatz

                    That's very clear and final.

                    Thanks a lot :)