13 Haziran 2012 Çarşamba

Richfaces reRender does not work after validation error

hi again folks, another strange problem with jsf behavior. For example you have a data grid and when u double click in a row you open up a pop up which contains a separate form and some fields on this pop up contains required attribute. When you submit this form required fields empty you will get a validation error. Till this time everything is ok but strange things starts after this.
You closed the form popup and this time clicked another row on data table and what you see is really strange you see the pop up form with the same values after validation error. According to guys at rich faces forums this is normal and it is because of nature of jsf. U may comment this situation as you should re set bean values but you are already doing this so what to do?
Yes again according to guys at rich faces forums you should reset the popup form. You can do this by defining an action listener each time opening the new form with the code given below. I took these code from rich faces forums and needed to change it a bit because of my page structure. Anyway here is the code and its explanation. Hope it ll work same as it worked for me.
Note all trick in this example is if rerender is not working for a form you need to define an action listener. And you need to indicate your form's id in the reRender list of your action. Indicating parent of the form does not work in this example.
Page Example:

<rich:dataTable width="100%" id="channelTable"
value="#{crmChannelAdminViewBean.chInfoList}" var="chan"
onRowMouseOver="this.style.backgroundColor='#F1F1F1'"
onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'"
onRowDblClick="selectRow('#{chan.id}')" rowClasses="gridCursor">
 
<a4j:jsFunction name="selectRow"
 action="#{crmChannelAdminViewBean.selectRow}" status="actionStatus"
 reRender="internetDetailForm,mpChannelDetail"
 ajaxSingle="true"
 oncomplete="if(data == true){#{rich:component('mpMessages')}.show();} else {#  {rich:component('mpChannelDetail')}.show();}" 
 data="#{channelTestViewBean.error}">
    <a4j:actionparam name="param1" assignTo="#{crmChannelAdminViewBean.selectedRow}"/> <f:actionListener    type="com.foobank.crm.common.util.A4JFormReset" /> 
</a4j:jsFunction>

  
package com.foobank.crm.common.util;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;

import org.ajax4jsf.context.AjaxContext;

public class A4JFormReset implements ActionListener {

 
 /**
  * This function resets form values before rerendering
  * the form. Sometimes you may see that rerendering does
  * not work after validation errors. Despite updating
  * bean values you may not see actual values on forms after
  * validation errors. To solve this you may use this action
  * listener class.
  * https://community.jboss.org/thread/8446?start=15&tstart=0
  */
     public void processAction(ActionEvent event) throws AbortProcessingException {                
         FacesContext facesContext = FacesContext.getCurrentInstance();
         AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext);
         UIComponent root = facesContext.getViewRoot();          
          ajaxContext.addRegionsFromComponent(event.getComponent());
         Set ids = ajaxContext.getAjaxAreasToRender();        
         List formIds = new LinkedList();

         for (String id : ids) {
               UIComponent form = root.findComponent(id);
               if (form != null && !formIds.contains(form.getId())) {
                   clearComponentHierarchy(form);
                   formIds.add(form.getId());
               }
          }
     }

    public UIComponent findParentForm(UIComponent component) {      
         for (UIComponent parent = component; parent != null; parent = parent.getParent()) {
               if (parent instanceof UIForm) {
                    return parent;
               }
          }          
          return null;
     }

     public 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 iterator = pComponent.getFacetsAndChildren(); iterator.hasNext();) {
                    clearComponentHierarchy(iterator.next());
               }          

          }
     }

}

Hiç yorum yok:

Yorum Gönder