验证失败后的Primefaces JSF更新失败

问题描述:

我在验证<p:inputText>并更新其内容时遇到问题。验证失败后的Primefaces JSF更新失败

基本上,当inputText验证失败时,它永远不会再被更新。

这里有一个简单的例子来阐明:

的一个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&#160; 
        <p:commandLink action="#{Test.assignElement}" update="detail_value"> 
         <f:setPropertyActionListener target="#{Test.currentElement}" value="1" /> 
         Assign 
        </p:commandLink> 
       </li> 
       <li>Element 2&#160; 
        <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> 

测试豆:

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 S中输入字段得到更新,但是当验证失败时(简单地将输入文本留空,并单击页面的任何其他部分),输入的边框变为红色。之后,点击上面提到的commandLinks后再也不会再更新。

任何想法?

Arjan tijms答案的作品,不过我找到了最好的解决方案是:

  1. 使用Omnifaces Solution 所以,而不是实施听众你的自我所有你需要的只是一行简单的代码。

    <h:commandButton value="Update" action="#{bean.updateOtherInputs}"> 
    <f:ajax execute="currentInputs" render="otherInputs" /> 
    <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" /> 
    </h:commandButton> 
    
  2. 如果您正在使用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> 
    

这是'input elements'(实际为EditableValueHolder s)的臭名昭着的情况,一旦验证失败,它们永远不会再通过AJAX重新呈现更新。

请参见:

  1. JSF AJAX validation: execute="@this" render="@form" inconsistent depending on prior requests
  2. How can I populate a text field using PrimeFaces AJAX after validation errors occur?
  3. http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1060

一个解决办法是建立一个动作监听器复位将被重新渲染的成分。看到这个的最后一页:http://community.jboss.org/message/620000

如果这种行为困扰你(我猜是这样),那么请不要犹豫,为JAVASERVERFACES_SPEC_PUBLIC-1060投票,如果可能的话留下评论,告诉你的预期和原因。

我会回答我自己。

基于Arjan提供的链接,我开发了actionListener来清理表单元素。它的工作原理。

的一个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>  

与听者....

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; 
    } 

}