Input fields hold previous values only if validation failed
Asked Answered
P

4

15

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?

Popedom answered 17/1, 2013 at 3:20 Comment(3)
I know this won't help you to understand the problem, but you shouldn't trust in the controller (the server side) to clear values in the view (the JSF page) when this can be done with plain Javascript (this applies in the New <a4j:commandButton> only).Clubhaul
Thanks for your suggestion about using javascript. I'll try it and inform you as soon as I got a time.Popedom
@LuiggiMendoza: I used javascript and had some success. But my real situation is little bit complex and I couldn't use javascript for my current real situation. However thank you very much for the hint and I hope to add the javascript workaround as an answer to this question for other peoples use when I got a time. :)Popedom
A
34

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);
Algiers answered 17/1, 2013 at 13:34 Comment(3)
BalusC, I really appreciate your answer. It helped me to solve my problem. I changed my newData() method according to your example and in my edit(data) method I used nameInput.setValue(data.getName()); nameInput.setSubmittedValue(data.getName());nameInput.setLocalValueSet(false); nameInput.setValid(true);. This works fine. Could you please explain what setLocalValueSet() method does. Thanks again.Popedom
It hints JSF during validations phase if the component has already been successfully validated or not. The isValid() returns also true if the component has not been validated yet. Only if validation has failed, it returns false. The isLocalValueSet() returns false if the component has not been validated yet. But if it is successfully been validated, then the local value will be set and the isLocalValueSet() will return true.Algiers
Hi BalusC. Is there something similar in ADF Faces ? I don't want to call resetValue() because the Button and the inputTexts resides in different regions and also they are in an af:iterator and I want a clean solution.Nanettenani
W
1

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.

Wakeup answered 17/1, 2013 at 9:57 Comment(0)
N
1

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.

Nonconductor answered 23/5, 2017 at 0:11 Comment(1)
The question was about JSF1.2 and RichFaces (RichFaces != PrimeFaces and the PrimeFaces version that has this functionality does not support JSF 1.2). Besides it (almost) was already in the accepted answer (and now is fully) Better to edit the existing wel explained question next time... But thanks for reminding us for this detail... (maybe comment on the answer is an option to).Unbodied
E
-2

After validation failed if you want to remain same as input data which you have pass as submission parameter, then set value attribute as your form bean name as mention below i.e.

<input type="text" id="fname" path="fname" value="${myFormBean.fname}"/>
Eisenstein answered 29/3, 2020 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.