[英]Primefaces JSF update after validation failed doesn't work
I have a problem with the validation of a <p:inputText>
and updating its content.我在验证
<p:inputText>
和更新其内容时遇到问题。
Basically when the inputText validation fails, it never gets updated again.基本上当 inputText 验证失败时,它永远不会再次更新。
Here's a simple example to clarify:这是一个简单的例子来澄清:
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>
The Test 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 "";
}
}
If you click on the commandLinks below the "Element"s the input field gets updated, but when a validation fails (simply leave the input text blank, and click on any other part of the page), the border of the input turns red.如果您单击“元素”下方的命令链接,输入字段会更新,但当验证失败时(只需将输入文本留空,然后单击页面的任何其他部分),输入的边框将变为红色。 After that it never gets updated again when clicking on the above mentioned commandLinks.
之后,单击上述命令链接时,它再也不会更新。
Any ideas?有任何想法吗?
Arjan tijms answer will works, however the best solutions I found are: Arjan tijms的答案是有效的,但我找到的最佳解决方案是:
Use Omnifaces Solution So, instead of implementing the listener your self all what you need is just one line of simple code. 使用Omnifaces解决方案因此,不是实现监听器,而是您需要的只是一行简单代码。
<h:commandButton value="Update" action="#{bean.updateOtherInputs}"> <f:ajax execute="currentInputs" render="otherInputs" /> <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" /> </h:commandButton>
If you are using Primefaces you can use resetInput component : 如果您使用的是Primefaces,可以使用resetInput组件 :
<p:commandButton value="Reset Non-Ajax" actionListener="#{resetInputView.reset}" immediate="true" ajax="false" style="margin-right:20px;"> <p:resetInput target="panel" /> </p:commandButton>
This is the notorious case of 'input elements' ( EditableValueHolder
s actually) that once validation has failed for them can never be updated again via AJAX re-rendering. 这是“输入元素”(实际上是
EditableValueHolder
)的臭名昭着的情况,一旦验证失败,它们就永远无法通过AJAX重新渲染再次更新。
See: 看到:
A work-around is to create an action listener that resets the components that are to be re-rendered. 解决方法是创建一个动作侦听器,重置要重新渲染的组件。 See the last page of this: http://community.jboss.org/message/620000
请参见最后一页: http : //community.jboss.org/message/620000
If this behavior bothers you (I guess it does), then please don't hesitate to vote for JAVASERVERFACES_SPEC_PUBLIC-1060 and if possible leave a comment telling what you expected and why. 如果这种行为困扰你(我猜它确实如此),那么请不要犹豫,投票支持JAVASERVERFACES_SPEC_PUBLIC-1060 ,如果可能的话,留下评论告诉你的期望和原因。
I will answer myself. 我会自己回答。
Based on the links provided by Arjan, i develop the actionListener to clean the form elements. 根据Arjan提供的链接,我开发了actionListener来清理表单元素。 and It works.
它的工作原理。
THE FACELET: 手镯:
<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>
And the LISTENER.... 和听众......
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;
}
}
to simplify the answer of Samy Omar for primefaces you just need to add PrimeFaces.current().resetInputs("form");
要简化Samy Omar对 primefaces 的回答,您只需添加
PrimeFaces.current().resetInputs("form");
somewhere in the listener or add <p:resetInput target="form"/>
inside the button to reset the inputs.在监听器的某处或在按钮内添加
<p:resetInput target="form"/>
以重置输入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.