Поля ввода сохраняют предыдущие значения только в случае неудачной проверки

У меня возникла странная проблема. Я попытался изолировать проблему, поэтому следующий мой упрощенный код.

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>

Это путь к ошибке:

  • Загрузите страницу
  • Нажмите ссылку "Изменить" в первой строке (всплывающие окна)
  • В всплывающем окне очистите поле "Возраст" и нажмите "Сохранить". (Обязательное сообщение показано)
  • Нажмите "Отменить" (без заполнения поля "Возраст" )
  • Нажмите вторую ссылку.
  • Теперь он показывает нерелевантные данные (предыдущие данные). - Это проблема.
  • Даже когда я нажимаю кнопку "Создать", отображаются неправильные данные.

Это происходит только в том случае, если во всплывающем окне не удалось выполнить проверку.
Есть ли решение для этого?

Ответ 1

Эта проблема находится в JSF 2, которая также распознается и подробно объясняется в следующем ответе: Как заполнить текстовое поле с помощью PrimeFaces AJAX после ошибок проверки? вы использовали JSF 2, вы могли бы использовать OmniFaces ResetInputAjaxActionListener или PrimeFaces <p:resetInput> или resetValues="true" для этого.

В связи с этим вам нужно очистить состояние компонента EditableValueHolder, когда он будет представлен как ajax-rendered, но который не входит в ajax-execute. Чтобы очистить состояние, в JSF 2 вы использовали бы метод удобства resetValue(), но это не доступно в JSF 1.2 и вам нужно вызвать 4 отдельных метода setValue(null), setSubmittedValue(null), setLocalValueSet(false), setValid(true), чтобы очистить состояние.

Чтобы выяснить, какие компоненты должны быть обработаны ajax, но не были выполнены ajax, в JSF 2 вы использовали бы методы PartialViewContext для этого, но это не доступно в JSF 1.2, стандартизированный аякс. Вам нужно будет возиться с конкретным API-интерфейсом RichFaces, чтобы понять это. Я не могу сказать это сверху, так что вот пример запуска, предполагающий, что вы уже знаете компоненты, которые нужно очистить. Представьте, что форма в вашем всплывающем окне имеет id="popForm", а поле ввода имени имеет id="nameInput", здесь, как вы можете очистить его внутри метода newData():

UIInput nameInput = (UIInput) context.getViewRoot().findComponent("popForm:nameInput");
nameInput.setValue(null);
nameInput.setSubmittedValue(null);
nameInput.setLocalValueSet(false);
nameInput.setValid(true);

Ответ 2

выполнить одно действие при отмене действия, установить все значения всплывающего окна null. теперь в следующем клике все значения будут установлены по умолчанию.

или при щелчке установите все предыдущие значения null. и после этого установите все соответствующие значения.

Ответ 3

У меня была та же проблема. если вы используете Primefaces, решение так же просто, как положить resetValues="true" на ваш p: commandLink или p: commandButton, который загружает выбранный элемент.