7 Replies Latest reply on Aug 2, 2007 10:35 PM by ishabalov

    reRender not working for h:inputText

    ralf.mueller

      I have a problem reRendering h:inputText fields. OutputText fields are reRendered properly, but nothing happens to the input fields. Am I missing something? The jsp snipet looks something like this:


      <a4j:form id="contractsForm" reRender="#{defaultValues.reRenderIDs}" >
      <h:panelGrid id="contractDetails" columns="1">
      <t:inputCalendar id="contracts_contractStartDateID"
      value="#{rentalContracts.contractStartDate}"
      displayValueOnly="#{rentalContracts.contractStatus == 'V'}"
      required="true" renderAsPopup="true"
      renderPopupButtonAsImage="true"
      popupButtonStyle="z-index:2000"
      styleClass="standardInputDateComponent"
      valueChangeListener="#{rentalContracts.changeListener}">
      <f:convertDateTime pattern="dd.MM.yyyy" timeZone="CET" />
      <f:validator validatorId="contractPeriodValidator" />
      <a4j:support action="#{rentalContracts.recalculateDuration}"
      event="onchange" reRender="#{defaultValues.reRenderIDs}"
      ajaxSingle="true"
      onsubmit="gowaitContracts()"
      oncomplete="goContracts()"/>
      </t:inputCalendar>

        • 1. Re: reRender not working for h:inputText

          Hmm.

          1. You have no h:inputText in your code snippet
          2. reRender attribute of a4j:form is void without ajaxSubmit="true"
          3. a4j:form with reRender should not to be used together with a4j:support
          4. According to JSF spec inputText renderer (as any other input component renderers) is responsible DO NOT to be updated from the model if the submitted value exists

          • 2. Re: reRender not working for h:inputText
            ralf.mueller

            Ok, sorry, I played around with the code a bit, because I didnt know what is wrong. So what it actually does is if you change the value in one of the fields. the value in the other field is changed through the backing Bean.
            So here comes the original code:

            <h:form id="contractsForm">
            <h:inputText id="contracts_contractRebatePercentageID"
            value="#{rentalContracts.contractRebatePercentage}"
            readonly="#{rentalContracts.contractStatus == 'V'}"
            styleClass="standardOutputText"
            valueChangeListener="#{rentalContracts.changeListener}">
            <f:convertNumber minFractionDigits="2" maxFractionDigits="2" />
            <f:validateDoubleRange minimum="0.00" maximum="999.99" />
            <a4j:support action="#{rentalContracts.recalculateContract}"
            event="onchange" reRender="#{defaultValues.reRenderIDs}"
            ajaxSingle="true" onsubmit="gowaitContracts()"
            oncomplete="goContracts()"/>
            </h:inputText>

            <h:inputText id="contracts_contractTotalMinusRebateID"
            value="#{rentalContracts.contractTotalMinusRebate}"
            readonly="#{rentalContracts.contractStatus == 'V'}"
            styleClass="standardOutputText">
            <f:convertNumber minFractionDigits="2" maxFractionDigits="2" /> <f:validateDoubleRange minimum="0.00" maximum="9999999.99" />
            <a4j:support action="#{rentalContracts.changeContractPrice}"
            event="onchange" reRender="#{defaultValues.reRenderIDs}"
            ajaxSingle="true" onsubmit="gowaitContracts()"
            oncomplete="goContracts()"/>
            </h:inputText>

            • 3. Re: reRender not working for h:inputText
              ralf.mueller

              Ok, I got it now. So I have to include the inputtext in a a4j:region.
              This means that on the server side only this value is submitted. If both are submitted, its not updated because the value exists?

              • 4. Re: reRender not working for h:inputText

                if you have an h:inputText value="#{foo.bar}" there is 4 (four!) places where the value is stored during the lifecycle.

                One is the 'bar' property of the 'foo' bean. It is easy. Where are three others?

                h:inputText is a component. The instance of it belongs to the component tree. Does this instance contains the value? Yes! It names 'local value'. It has the same type, the 'bar' property has. So, if 'bar' is java.util.Date, the local value has the same type.
                What if user types and submits some garbage, but not a date? Hey, JSF is not so stupid. It reserved the 'submitted value' for this case. This is a third placeholder.

                The fourth place is a request parameters map. The typed value comes with request before it the submitted value is assigned.

                Ideally: The submitted value should be checked against the converter and only, if it is OK, the local value is updated and the submitted value is cleaned up.
                Then, only is validation and update phases are passed successfully, the model value (ie. foo.bar itself) is updated and the local value is cleaned up.

                Why I said "Ideally"? Because JSF is not stupid, but its implementations are buggy (from version to version in different degree). Sometimes, the local value or submitted value are not cleaned up.

                This does not matter if the navigation brings to the news view page. In this case, the old component tree is void, and a new fresh tree is created.

                However, if the lifecycle comes to the RENDER RESPONSE phase with the same tree (and this is always true for Ajax Request/Response), the component renderer should be smart enough to resolve the situation.

                Assume, user enters the wrong date. The page after reload should show the value user entered, but not the old one from the model. Right?

                Ideally, the algorithm is following:
                * if submitted value is not empty, grab it and show
                * otherwise, if local value is not null, show it
                * otherwise, call getter of the model value and show it

                To make a long story short, I am not going to explain why I said 'Ideally' again. It is up to your imagination.

                Conclusion: there are too many 'if', 'only if', 'ideally' should be matched before what is obvious from your point of view (taking value from the model) can happen.

                So, do not play with the fire. Be proactive. There are many ways:
                1. do not submit the value at all. You can do it using ajaxSingle attribute.
                This does not work for select type components (Why? This is a theme for another tale)
                2. do not process the other input. This is achieved with surrounding the first input with a4j:region
                3. use binding on the second input. The binding allows you to access to the component object. You can clean up the submitted and local values to make updating from the model works OR put the new value to the local value directly and let component renderer to feel how much it is smart.

                • 5. Re: reRender not working for h:inputText

                   

                  "ralf.mueller" wrote:
                  Ok, I got it now. So I have to include the inputtext in a a4j:region.
                  This means that on the server side only this value is submitted. If both are submitted, its not updated because the value exists?


                  BINGO!

                  • 6. Re: reRender not working for h:inputText
                    ralf.mueller

                    Thanks a lot. I think I got a much better understanding of the whole process now.

                    • 7. Re: reRender not working for h:inputText

                      I've put together small sample about your problem:

                      http://ishabalov.blogspot.com/2007/08/sad-story-about-uiinput.html