Первичное обновление JSF после неудачной проверки не работает
У меня проблема с проверкой a <p:inputText>
и обновлением его содержимого.
В основном, когда проверка входного текста завершается неудачно, он никогда не обновляется повторно.
Вот простой пример для пояснения:
The Facelet:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<body>
<h1>Test</h1>
<h:form id="list" prependId="false">
<ul>
<li>Element 1 
<p:commandLink action="#{Test.assignElement}" update="detail_value">
<f:setPropertyActionListener target="#{Test.currentElement}" value="1" />
Assign
</p:commandLink>
</li>
<li>Element 2 
<p:commandLink action="#{Test.assignElement}" update="detail_value">
<f:setPropertyActionListener target="#{Test.currentElement}" value="2" />
Assign
</p:commandLink>
</li>
</ul>
</h:form>
<h:form id="detail" prependId="false">
<p:inputText value="#{Test.element}" id="detail_value" required="true" styleClass="#{Faces.messagesFor['detail_value'] ? 'border:1px solid red' : ''}">
<p:ajax event="blur" update="detail_value"></p:ajax>
</p:inputText>
</h:form>
</body>
</html>
Тест bean:
package com.easydevel.test;
public class Test {
private String currentElement;
private String element;
public String getCurrentElement() {
return currentElement;
}
public void setCurrentElement(String currentElement) {
this.currentElement = currentElement;
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
public String assignElement(){
setElement(getCurrentElement());
return "";
}
}
Если вы нажмете на commandLinks под "Element", поле ввода будет обновлено, но когда проверка не удастся (просто оставьте текст ввода пустым и щелкните любую другую часть страницы), граница ввода становится красным. После этого он не будет обновляться снова, когда вы нажимаете на вышеупомянутые командыLinks.
Любые идеи?
Ответы
Ответ 1
Arjan tijms будет работать, однако лучшие решения, которые я нашел, следующие:
-
Использовать Решение Omnifaces
Таким образом, вместо того, чтобы внедрять слушателя самостоятельно, все, что вам нужно, это всего лишь одна строка простого кода.
<h:commandButton value="Update" action="#{bean.updateOtherInputs}">
<f:ajax execute="currentInputs" render="otherInputs" />
<f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
</h:commandButton>
-
Если вы используете Primefaces, вы можете использовать resetInput component:
<p:commandButton value="Reset Non-Ajax" actionListener="#{resetInputView.reset}"
immediate="true" ajax="false" style="margin-right:20px;">
<p:resetInput target="panel" />
</p:commandButton>
Ответ 2
Это печально известный случай "входных элементов" (фактически EditableValueHolder
), которые после того, как проверка не удалась для них, никогда не могут быть снова обновлены с помощью повторной рендеринга AJAX.
См:
Обход - это создание прослушивателя действий, который сбрасывает компоненты, которые должны быть повторно отображены. См. Последнюю страницу: http://community.jboss.org/message/620000
Если это вас беспокоит (я думаю, это так), то, пожалуйста, не стесняйтесь голосовать за JAVASERVERFACES_SPEC_PUBLIC-1060 и, если возможно, оставьте комментарий, рассказывая, что вы ожидали и почему.
Ответ 3
Я отвечу сам.
На основе ссылок, предоставленных Arjan, я разрабатываю actionListener для очистки элементов формы. и он работает.
ФАСЕЛЕТ:
<p:commandLink action="#{Test.assignElement}" update="detail_value">
<f:actionListener type="com.easydevel.utils.CleanForms" />
<f:setPropertyActionListener target="#{Test.currentElement}" value="1" />
Assign
</p:commandLink>
И СПИСОК ЛЮБИТЕЛЕЙ....
package com.easydevel.utils;
import java.util.Collection;
import java.util.Iterator;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialViewContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
public class CleanForms implements ActionListener {
public void processAction(ActionEvent event) throws AbortProcessingException {
FacesContext facesContext = FacesContext.getCurrentInstance();
PartialViewContext ajaxContext = facesContext.getPartialViewContext();
UIComponent root = facesContext.getViewRoot();
Collection<String> renderIds = ajaxContext.getRenderIds();
for (String renderId : renderIds) {
UIComponent form = findComponent(root,renderId);
if (form != null) {
clearComponentHierarchy(form);
}
}
}
private void clearComponentHierarchy(UIComponent pComponent) {
if (pComponent.isRendered()) {
if (pComponent instanceof EditableValueHolder) {
EditableValueHolder editableValueHolder = (EditableValueHolder) pComponent;
editableValueHolder.setSubmittedValue(null);
editableValueHolder.setValue(null);
editableValueHolder.setLocalValueSet(false);
editableValueHolder.setValid(true);
}
for (Iterator<UIComponent> iterator = pComponent.getFacetsAndChildren(); iterator.hasNext();) {
clearComponentHierarchy(iterator.next());
}
}
}
private static UIComponent findComponent(UIComponent base, String id) {
if (id.equals(base.getId()))
return base;
UIComponent kid = null;
UIComponent result = null;
Iterator kids = base.getFacetsAndChildren();
while (kids.hasNext() && (result == null)) {
kid = (UIComponent) kids.next();
if (id.equals(kid.getId())) {
result = kid;
break;
}
result = findComponent(kid, id);
if (result != null) {
break;
}
}
return result;
}
}