ICEfaces
  1. ICEfaces
  2. ICE-9676

ace:autoCompleteEntry Temporary Text value Overriding Component Value

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: EE-3.3.0.GA_P01
    • Fix Version/s: 4.0.BETA, EE-3.3.0.GA_P02, 4.0
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      JBoss
    • Assignee Priority:
      P1
    • Salesforce Case Reference:

      Description

      In the client application, the ace:autoCompleteEntry tag value is being set appropriately and then the user is changing the page content to another include. Upon returning to the original include with the ace:autoCompleteEntry, the value bound to the component is reset in the bean. However, the component is dislaying the previously entered (temporary text) value.

      With direction from Art, I replaced the ace:autoCompleteEntry component with the ace:comboBox component and was not able to reproduce the issue. This suggests the problem is with the temporary text value unique to the ace:autoCompleteEntry component.

        Issue Links

          Activity

          Hide
          Brad Kroeger added a comment -

          In the showcase ace:autoCompleteEntryLazy.xhtml I have the component configured as follows:

          <ace:autoCompleteEntry id="autoCompleteEntryLazy"
          value="#

          {autoCompleteEntryLazyBean.selectedText}

          "
          rows="10" width="300"
          filterMatchMode="none"
          listVar="city"
          listValue="#

          {autoCompleteEntryLazyBean.cities}

          "
          filterBy="#

          {city.name}"
          textChangeListener="#{autoCompleteEntryLazyBean.textChangeEventHandler}"
          label="Cities of the World:"
          labelPosition="left"
          valueChangeListener="#{autoCompleteEntryLazyBean.cityValueChange}">
          <f:facet name="row">
          <h:panelGrid columns="2" width="100%" columnClasses="col50,col25">
          <h:outputText value="#{city.name}

          " />
          <h:outputText value="#

          {city.country}

          " />
          </h:panelGrid>
          </f:facet>
          <ace:ajax execute="@form" render="@form" event="submit"/>
          <ace:ajax execute="@form" render="@form" event="blur"/>
          </ace:autoCompleteEntry>

          I add the following to the page:
          <h:commandButton value="Clear Bean Value"
          actionListener="#

          {autoCompleteEntryLazyBean.clearBeanValue}

          " />

          And the corresponding bean code:
          public void clearBeanValue(ActionEvent ae)

          { selectedText = null; }

          When I press the button to clear the value, I see the response code for the component with an empty String ''. However, the component still retains it's old value in the UI. If you switch from another demo back to 'Lazy Loading' you will see the old value still in the UI.

          Show
          Brad Kroeger added a comment - In the showcase ace:autoCompleteEntryLazy.xhtml I have the component configured as follows: <ace:autoCompleteEntry id="autoCompleteEntryLazy" value="# {autoCompleteEntryLazyBean.selectedText} " rows="10" width="300" filterMatchMode="none" listVar="city" listValue="# {autoCompleteEntryLazyBean.cities} " filterBy="# {city.name}" textChangeListener="#{autoCompleteEntryLazyBean.textChangeEventHandler}" label="Cities of the World:" labelPosition="left" valueChangeListener="#{autoCompleteEntryLazyBean.cityValueChange}"> <f:facet name="row"> <h:panelGrid columns="2" width="100%" columnClasses="col50,col25"> <h:outputText value="#{city.name} " /> <h:outputText value="# {city.country} " /> </h:panelGrid> </f:facet> <ace:ajax execute="@form" render="@form" event="submit"/> <ace:ajax execute="@form" render="@form" event="blur"/> </ace:autoCompleteEntry> I add the following to the page: <h:commandButton value="Clear Bean Value" actionListener="# {autoCompleteEntryLazyBean.clearBeanValue} " /> And the corresponding bean code: public void clearBeanValue(ActionEvent ae) { selectedText = null; } When I press the button to clear the value, I see the response code for the component with an empty String ''. However, the component still retains it's old value in the UI. If you switch from another demo back to 'Lazy Loading' you will see the old value still in the UI.
          Hide
          Arturo Zambrano added a comment -

          Committed fix to 4.0 trunk at revision 38762 and to 3.3 EE maintenance branch at revision 38763.

          Show
          Arturo Zambrano added a comment - Committed fix to 4.0 trunk at revision 38762 and to 3.3 EE maintenance branch at revision 38763.
          Hide
          Brad Kroeger added a comment -

          I tested this in my client application and it's still not working. Unfortunately, I cannot recreate this in the showcase or my prototype application.

          I walked through the steps with Art. The difference I'm seeing from the previous jars is that previously, when I cleared the value on the server, the js in the response appeared to be trying to set the value to an empty String (which was expected) but the 'temporary' value was being displayed.

          Now, when the server side value is set to null I'm seeing the js trying to set the value to the previous value:
          (function()

          {var instance = ice.ace.Autocompleters["iepeFrm:paNbrTxt1"];instance.updateField('5001809', false);}

          )();

          Art thinks he knows what is happening here and instructed me to reopen the issue.

          Show
          Brad Kroeger added a comment - I tested this in my client application and it's still not working. Unfortunately, I cannot recreate this in the showcase or my prototype application. I walked through the steps with Art. The difference I'm seeing from the previous jars is that previously, when I cleared the value on the server, the js in the response appeared to be trying to set the value to an empty String (which was expected) but the 'temporary' value was being displayed. Now, when the server side value is set to null I'm seeing the js trying to set the value to the previous value: (function() {var instance = ice.ace.Autocompleters["iepeFrm:paNbrTxt1"];instance.updateField('5001809', false);} )(); Art thinks he knows what is happening here and instructed me to reopen the issue.
          Hide
          Brad Kroeger added a comment -

          I also tried explicitly setting the value bound to the ui to null (the client application code doesn't set the instance variable to null, but re-instantiates a new instance of the parent class). This did not make a difference.

          Show
          Brad Kroeger added a comment - I also tried explicitly setting the value bound to the ui to null (the client application code doesn't set the instance variable to null, but re-instantiates a new instance of the parent class). This did not make a difference.
          Hide
          Arturo Zambrano added a comment -

          Committed fix for issue described in last two comments to the trunk at revision 38807 and to the 3.3 EE branch at revision 38812.

          Show
          Arturo Zambrano added a comment - Committed fix for issue described in last two comments to the trunk at revision 38807 and to the 3.3 EE branch at revision 38812.
          Hide
          Arturo Zambrano added a comment -

          The previous fix was reverted since it had some negative side effects. Instead, a new 'reset' attribute was added for completely resetting all temporary values that the component stores permanently. This flag would typically be set to true in an action listener. It is advised that the value property is also set to null in the same action listener. The flag automatically is set back to false after it is consumed.

          It wasn't possible to fix this issue in a more transparent way. The intended fix was to avoid rendering the updateField() call when doing a textChange request or when the main value was null, leaving the field updates only to requests that set the main value. This wasn't possible and caused other problems. First of all, we need to always call updateField() because that's the only way we populate the text field, since we don't directly render the component value in the input element for a number of good reasons. If we did, the input element would have to be updated every time we type a character and we would have to re-initialize the component in the client every time as well, to apply all the listeners to the input element. Moreover, we need to always call updateField() because certain requests cause a full update of the component's markup, and since we don't render the component value directly to the input element, we need to keep the value in the text field up to date. One example is when the component fails validation; new CSS class names are added and the aria-invalid="true" attribute is added as well. This causes a full markup update, and therefore we need to update the text field. Another example is when there are changes with labels and indicators, which change the markup structure and require a full markup update of the component. There are also other domdiff concerns that require us to always update the value via a call to updateField().

          Show
          Arturo Zambrano added a comment - The previous fix was reverted since it had some negative side effects. Instead, a new 'reset' attribute was added for completely resetting all temporary values that the component stores permanently. This flag would typically be set to true in an action listener. It is advised that the value property is also set to null in the same action listener. The flag automatically is set back to false after it is consumed. It wasn't possible to fix this issue in a more transparent way. The intended fix was to avoid rendering the updateField() call when doing a textChange request or when the main value was null, leaving the field updates only to requests that set the main value. This wasn't possible and caused other problems. First of all, we need to always call updateField() because that's the only way we populate the text field, since we don't directly render the component value in the input element for a number of good reasons. If we did, the input element would have to be updated every time we type a character and we would have to re-initialize the component in the client every time as well, to apply all the listeners to the input element. Moreover, we need to always call updateField() because certain requests cause a full update of the component's markup, and since we don't render the component value directly to the input element, we need to keep the value in the text field up to date. One example is when the component fails validation; new CSS class names are added and the aria-invalid="true" attribute is added as well. This causes a full markup update, and therefore we need to update the text field. Another example is when there are changes with labels and indicators, which change the markup structure and require a full markup update of the component. There are also other domdiff concerns that require us to always update the value via a call to updateField().
          Hide
          Arturo Zambrano added a comment -

          Committed fix described above to the 4.0 trunk at revision 39047 and to the 3.3 EE maintenance branch at revision 39048.

          Show
          Arturo Zambrano added a comment - Committed fix described above to the 4.0 trunk at revision 39047 and to the 3.3 EE maintenance branch at revision 39048.

            People

            • Assignee:
              Arturo Zambrano
              Reporter:
              Brad Kroeger
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: