Primefaces JSF update after validation failed doesn't work

若如初见. 提交于 2019-12-03 10:34:29
Samy Omar

Arjan tijms answer will works, however the best solutions I found are:

  1. Use Omnifaces Solution So, instead of implementing the listener your self all what you need is just one line of simple code.

    <h:commandButton value="Update" action="#{bean.updateOtherInputs}">
    <f:ajax execute="currentInputs" render="otherInputs" />
    <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
    </h:commandButton>
    
  2. If you are using Primefaces you can use 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>  
    
Arjan Tijms

This is the notorious case of 'input elements' (EditableValueHolders actually) that once validation has failed for them can never be updated again via AJAX re-rendering.

See:

  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

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

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.

I will answer myself.

Based on the links provided by Arjan, i develop the actionListener to clean the form elements. 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;
   }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!