javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2490

UIData does not keep submitted value when there is no error with a immediate button

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Works as designed
    • Affects Version/s: 2.1.19
    • Fix Version/s: None
    • Component/s: ajax
    • Labels:
      None
    • Environment:

      glassfish 3.1.2

      Description

      I have dataTable which contains inputText child. Outside of the datatable, there is an ajax button which add more value to datatable model data and refresh the datatable. Basically, I use ajax to add new row to datatable. The immediate is set to true for ajax since I do not want to validate the entered data in datatable at this time. However, I do not want to lose any data already entered by the user. So the whole datatable is sent to server for execution. Since the button is set to immediate, the data inside datatable will not be validated and should be sent back to browser. But empty text is sent back, and entered data are lost.

      Test case:

      <h:form>
      		<h:dataTable  value="#{test.values}" var="item" id="tables">
      			<h:column>
      				<h:inputText value="#{item.value}"></h:inputText>
      			</h:column>
      		</h:dataTable>
      		<h:commandButton id="adder" value="Add" actionListener="#{test.action}" immediate="true">
      			<f:ajax	render="tables" execute="@form" listener="#{test.addOneValue}" immediate="true"></f:ajax>
      		</h:commandButton>
      	</h:form>
      

      Code

      @Named("test")
      @SessionScoped
      public class Test1 implements Serializable
      {
      
      	
      	
      	/**
      	 * 
      	 */
      	private static final long serialVersionUID = 1L;
      	List<ValueHolder<String>> values=new LinkedList<ValueHolder<String>>();
      
      	public List<ValueHolder<String>> getValues()
      	{
      		return values;
      	}
      
      	public void setValues(List<ValueHolder<String>> values)
      	{
      		this.values = values;
      	}
      	
      	public void addOneValue(javax.faces.event.AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException
      	{
      		values.add(new ValueHolder<String>());
      	}
      	
      	public void action()
      	{
      		System.out.println("called");
      	}
      	
      	
      	
      }
      

      I trace the code to keepSaved method in UIData class

      line 2176: private boolean keepSaved(FacesContext context) {
      
              return (contextHasErrorMessages(context) || isNestedWithinUIData());
      
          }
      

      To prove this,
      if I intentionally add a useless FacesMesage
      Modified Code

      public void addOneValue(javax.faces.event.AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException
      	{
      		values.add(new ValueHolder<String>());
      		FacesMessage msg=new FacesMessage("new item is added");
      		FacesContext.getCurrentInstance().addMessage(null, msg);
      	}
      

      This will make keepSaved return true. Entered data in datatable are sent back to browser.

      This issue is very similar to issue 73 which is closed. But I guess it is not fixed completely.

      1. jsf2490.tgz
        4 kB
        jasonzhang2002gmailcom

        Issue Links

          Activity

          Hide
          Manfred Riem added a comment -

          Can you reproduce the problem on the most recent 2.1 release?

          Show
          Manfred Riem added a comment - Can you reproduce the problem on the most recent 2.1 release?
          Hide
          jasonzhang2002gmailcom added a comment -

          The attached file is simple eclipse project to reproduce the problem. This problem also occurs in jsf 2.1_14, the latest release

          deploy it to glassfish, go to index.xhtml, change any text field, click "Add Row" button, the changed text is lost. Change any text again, click "Add Row With Message", the change is kept. The only difference between this two ajaxes is a useless FacesMessage in server.

          This should be an major issue instead of a minor one. UIData uses existence of FacesMessage to decide whether to send the submitted table back to user or not. This is a hack, isn't it?

          -jason

          Show
          jasonzhang2002gmailcom added a comment - The attached file is simple eclipse project to reproduce the problem. This problem also occurs in jsf 2.1_14, the latest release deploy it to glassfish, go to index.xhtml, change any text field, click "Add Row" button, the changed text is lost. Change any text again, click "Add Row With Message", the change is kept. The only difference between this two ajaxes is a useless FacesMessage in server. This should be an major issue instead of a minor one. UIData uses existence of FacesMessage to decide whether to send the submitted table back to user or not. This is a hack, isn't it? -jason
          Hide
          Manfred Riem added a comment -

          You mean 2.1.14 right?

          Show
          Manfred Riem added a comment - You mean 2.1.14 right?
          Hide
          jasonzhang2002gmailcom added a comment -

          I just tested with 2.1.19/2.2 milestone 09 and still see the problem in both releases

          Show
          jasonzhang2002gmailcom added a comment - I just tested with 2.1.19/2.2 milestone 09 and still see the problem in both releases
          Hide
          jasonzhang2002gmailcom added a comment -

          I tested this issue in 2.2.0 release. The issue still exists.
          I finally tracked down the issue. I detailed the problem here :http://blog.flexdms.com/2013/07/immediate-action-for-data-under-uidata.html.
          The issue boils down to this: In a ajax call, input data for component inside of UIData have gone through validation/update model phase. Otherwise, the submitted value are lost. This differs from how input component works outside of UIData.

          My understanding is this: To find out whether there is validation error, UIData(DataTable and UIRepeat) only checks the existence of error message in FacesContext. This is good enough in practice. But it is definitely not a ideal solution.

          This bug is not a big issue. Adding validation in my case is not ideal, but is not a big sacrifice. I guess you can change the priority to minor.

          -jason

          Show
          jasonzhang2002gmailcom added a comment - I tested this issue in 2.2.0 release. The issue still exists. I finally tracked down the issue. I detailed the problem here : http://blog.flexdms.com/2013/07/immediate-action-for-data-under-uidata.html . The issue boils down to this: In a ajax call, input data for component inside of UIData have gone through validation/update model phase. Otherwise, the submitted value are lost. This differs from how input component works outside of UIData. My understanding is this: To find out whether there is validation error, UIData(DataTable and UIRepeat) only checks the existence of error message in FacesContext. This is good enough in practice. But it is definitely not a ideal solution. This bug is not a big issue. Adding validation in my case is not ideal, but is not a big sacrifice. I guess you can change the priority to minor. -jason
          Hide
          Manfred Riem added a comment -

          Unfortunately you have hit on something that would require a specification change. See http://docs.oracle.com/javaee/6/api/javax/faces/component/UIData.html#encodeBegin(javax.faces.context.FacesContext)

          It states that per-row state of child components needs to be discarded, UNLESS it is needed to rerender the current page with errors. Your work-around basically triggers the UNLESS section.

          Please file a spec issue if you think this should be addressed in a future revision of the specification. Thanks!

          Show
          Manfred Riem added a comment - Unfortunately you have hit on something that would require a specification change. See http://docs.oracle.com/javaee/6/api/javax/faces/component/UIData.html#encodeBegin(javax.faces.context.FacesContext ) It states that per-row state of child components needs to be discarded, UNLESS it is needed to rerender the current page with errors. Your work-around basically triggers the UNLESS section. Please file a spec issue if you think this should be addressed in a future revision of the specification. Thanks!

            People

            • Assignee:
              Manfred Riem
              Reporter:
              jasonzhang2002gmailcom
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: