Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input fields hold previous values only if validation failed

I came up with a strange problem. I tried to isolate the problem so following is my simplified code.

public class MyBean {

  private List<Data> dataList;
  Data selectedData;

  public MyBean() {
    dataList = new ArrayList<Data>();
    dataList.add(new Data("John", 16));
    dataList.add(new Data("William", 25));
  }

  public List<Data> getDataList() {
    return dataList;
  }

  public void edit(Data data) {
    selectedData = data;
  }
  public void newData() {
    selectedData = new Data(null, null);
  }

  public Data getSelectedData() {
    return selectedData;
  }

  public class Data {
    String name;
    Integer age;
    Data(String name, Integer age) {
      this.name = name;
      this.age = age;
    }
    public String getName() {
      return name;
    }
    public void setName(String name) {
      this.name = name;
    }
    public Integer getAge() {
      return age;
    }
    public void setAge(Integer age) {
      this.age = age;
    }
  }
}

xhtml:

<rich:modalPanel id="pop">
  <h:form>
    Name: <h:inputText value="#{myBean.selectedData.name}" required="true" id="txtName"/><br/>
    Age : <h:inputText value="#{myBean.selectedData.age}" required="true" id="txtAge"/>
    <a4j:commandButton value="Save"/>
    <a4j:commandButton value="Close" onclick="Richfaces.hideModalPanel('pop');return false;"/>
    <br/>
    <rich:message for="txtName"/><br/>
    <rich:message for="txtAge"/>
  </h:form>     
</rich:modalPanel>

<h:form>
  <rich:dataTable value="#{myBean.dataList}" var="data">
    <rich:column>#{data.name}</rich:column>
    <rich:column>
      <a4j:commandLink value="Edit" action="#{myBean.edit(data)}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/>
    </rich:column>
  </rich:dataTable>
  <a4j:commandButton value="New" action="#{myBean.newData()}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/>
</h:form>

This is the path to error:

  1. Load the page
  2. Click the "Edit" link in first row(popup displays)
  3. In popup, clear the "Age" field and click "Save".(Required message shown)
  4. Click cancel(without filling "Age" field)
  5. Click second link.
  6. Now it shows irrelevant data(previous data). - This is the problem
  7. Even when I click "New" button it shows incorrect data.

This happens only if a validation is failed in the popup.
Is there a solution for this?

like image 242
prageeth Avatar asked Jan 17 '13 03:01

prageeth


3 Answers

This problem is in JSF 2 also recognized and explained in detail in the following answer: How can I populate a text field using PrimeFaces AJAX after validation errors occur? If you were using JSF 2, you could have used OmniFaces' ResetInputAjaxActionListener or PrimeFaces' <p:resetInput> or resetValues="true" for this.

To the point, you need to clear the state of the EditableValueHolder component when it's about to be ajax-rendered, but which isn't included in the ajax-execute. To clear the state, in JSF 2 you would have used the convenience method resetValue() for this, but this isn't available in JSF 1.2 and you need to invoke the 4 individual methods setValue(null), setSubmittedValue(null), setLocalValueSet(false), setValid(true) to clear the state.

To figure out which components are to be ajax-rendered, but aren't been ajax-executed, in JSF 2 you would have used PartialViewContext methods for this, but this is not available in JSF 1.2 which hasn't standardized ajax yet. You'd need to fiddle with RichFaces specific ajax API in order to figure that. I can't tell that from top of head, so here's a kickoff example assuming that you already know the components which needs to be cleared. Imagine that the form in your popup has id="popForm" and the name input field has id="nameInput", here's how you could clear it inside the newData() method:

UIInput nameInput = (UIInput) context.getViewRoot().findComponent("popForm:nameInput");
nameInput.setValue(null);
nameInput.setSubmittedValue(null);
nameInput.setLocalValueSet(false);
nameInput.setValid(true);
like image 144
BalusC Avatar answered Nov 15 '22 17:11

BalusC


do one thing on cancel action set all popup values null. now in your next click all values set to be default.

or on click set all previous values null. and set all respective values after that.

like image 1
durgesh6121 Avatar answered Nov 15 '22 19:11

durgesh6121


I had the same problem. if you are using Primefaces, the solution is as simple as putting resetValues="true" on your p:commandLink or p:commandButton that loads the selected item.

like image 1
hendinas Avatar answered Nov 15 '22 18:11

hendinas