1 2 Previous Next 24 Replies Latest reply on Jun 19, 2014 5:24 AM by marcelkolsteren Go to original post
      • 15. Re: Validation and refresh problems...
        henk53

        ilya_shaikovsky wrote:

         

        It's better to resolve this at JSF spec level by filling RFC there. Our approach is not to change functionality described in JSF spec but extend using standard extension points. From the point of view of your case it sounds reasonable. But as the submitted value needed in order to fire valueChangeEvent - such functionality will conflict with standard JSF functionality in its current state.

         

        I understand completely and I fully respect and applaud your decision to adhere to the JSF spec as much as possible. This should be indeed be the default as an absolute first priority.

         

        However, giving the user the option to explicitly override some behavior might be helpful here. As it is, JSF itself allows many of its parts to be replaced or augmented by the user if the user chooses to do so, possibly breaking compatibility at the user's own risk. Many third party libraries also have options for this (of course, never as a default).

         

        An option for RichFaces to force a re-rendering from source, with a clear warning that this might conflict with other JSF functionality, might not be that bad. By default the user would user the reRender attribute and only when absolutely necessary, would he use forceReRender. The word "force" already communicates that something out of the ordinary is happening.

         

        For the ones interested in it, I did wrote a small fairly universal actionlistener that one can include inside an a4j:actionLink or button:

         

        package com.something.faces;
        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 {
        
             @Override
             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<String> ids = ajaxContext.getAjaxAreasToRender();          
                  for (String id : ids) {
                       UIComponent form = findParentForm(root.findComponent(id));
                       if (form != null) {
                            clearComponentHierarchy(form);
                       }
                  }     
             }
             
             public UIComponent findParentForm(UIComponent component) {
                  if (component instanceof UIForm) {
                       return component;
                  }          
                  if (component == null) {
                       return null;
                  }          
                  return findParentForm(component.getParent());
             }
        
             public void clearComponentHierarchy(UIComponent pComponent) {
                  if (pComponent instanceof EditableValueHolder) {
                       EditableValueHolder editableValueHolder = (EditableValueHolder) pComponent;
                       editableValueHolder.setSubmittedValue(null);
                       editableValueHolder.setValue(null);
                       editableValueHolder.setValid(true);
                  }          
                  for (UIComponent child : pComponent.getChildren()) {
                       clearComponentHierarchy(child);
                  }
             }
             
        }
        

         

         

        This can be used on a JSF page like this:

         

        <a4j:commandLink value="test" action="#{bean.someMethod}" reRender="someID">
           <f:actionListener type="com.something.faces.A4JFormReset" />
        </a4j:commandLink>
        

         

         

        Since the actionListener fires before the commandLink gets a chance to setup its preRender stuff, I had to call ajaxContext.getAjaxAreasToRender() myself in advance. I hope I don't break anything with it, but I scanned the implementation source and it seems to be harmless. The commandLink will call it again anyway.

         

        I briefly tested this and it seems to work nicely. It's basically the code others have posted but wrapped in a more universal package. Maybe it's also not even needed to clear the whole form but just the target components.

         

        Ilya, if you do see anything really wrong in this code, please let us know.

        • 16. Re: Validation and refresh problems...
          nbelaevski

          Hi,

           

          Several corrections:

           

          - Non-rendered components and their children should be skipped

          - Facets should be also processed together with children

          - "localValueSet" attribute of EditableValueHolder should be also reset (this should be done after resetting "value" attribute, not before!)

          - findParentForm(UIComponent) is better to rewrite without recursion for performance improvement

          • 17. Re: Validation and refresh problems...
            henk53

            Several corrections:

             

            - Non-rendered components and their children should be skipped

            - Facets should be also processed together with children

            - "localValueSet" attribute of EditableValueHolder should be also reset (this should be done after resetting "value" attribute, not before!)

            - findParentForm(UIComponent) is better to rewrite without recursion for performance improvement

             

            Wow, thanks a lot. Those are very valuable suggestions. Even though I have been using JSF for some time, I'm not really that knowledgeable with the internals yet. This is the new version with your suggested improvements:

             

            package com.something.faces;
            
            import java.util.Iterator;
            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 {
                 @Override
                 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<String> ids = ajaxContext.getAjaxAreasToRender();          
                      for (String id : ids) {
                           UIComponent form = findParentForm(root.findComponent(id));
                           if (form != null) {
                                clearComponentHierarchy(form);
                           }
                      }
                 }
                 
                 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<UIComponent> iterator = pComponent.getFacetsAndChildren(); iterator.hasNext();) {
                                clearComponentHierarchy(iterator.next());
                           }          
                      }
                 }
            }
            
            • 18. Re: Validation and refresh problems...
              atijms

              I tried the action listener and it seems to work very well. Thanks to everyone involved for providing this.

               

              It maybe wouldn't be a bad idea for Rich faces if they shipped something like this action listener with the standard distribution.

              • 19. Re: Validation and refresh problems...
                julien.dramaix

                Nice code !! And works perfectly !

                 

                My little contribution : avoid to clear two times (or more) the same form if many components of the same form is in the reRender attributes.

                 

                 

                {code}

                package com.something.faces;

                 

                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 {

                 

                     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<String> ids = ajaxContext.getAjaxAreasToRender();       

                         List<String> formIds = new LinkedList<String>();

                 

                         for (String id : ids) {

                               UIComponent form = findParentForm(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<UIComponent> iterator = pComponent.getFacetsAndChildren(); iterator.hasNext();) {

                                    clearComponentHierarchy(iterator.next());

                               }         

                 

                          }

                     }

                 

                }

                {code}

                 

                Julien

                • 20. Re: Validation and refresh problems...
                  maggus

                  Why do you search for the form which holds the component which should be reRendered? why do you afterwards clear this form completly?

                   

                  why not only searching for the component and clear it (and maybe all child-components and facets which are related to this component)....?

                  • 21. Re: Validation and refresh problems...
                    henk53

                    Markus Staab wrote:

                     

                    Why do you search for the form which holds the component which should be reRendered? Why do you afterwards clear this form completely?

                     

                    To be honest, I'm not exactly sure anymore why this was done. I guess it was to keep the whole form in a consistent 'cleared' state, or maybe it would only work if all components were cleared. (anyway, Julien's addition is rather nice, the original code indeed potentially cleared the same form many times over)

                     

                    Also, in JSF 2.0 and RichFaces 4, the same problem applies but the solution is different. At the very least AjaxContext doesn't exist anymore.

                    • 22. Re: Validation and refresh problems...
                      rngarnaik

                      JSF 2.0 and Richfaces 4.0 not yet addressed this issue, what is the process to file RFC? Can richfaces guys able to fix this issue with enhanced functionality with a4j components?

                       

                      Anyway thaks guys for this post, we able to get the temporary solution for this issue .

                      • 23. Re: Validation and refresh problems...
                        henk53

                        Rudra Garnaik wrote:

                         

                        JSF 2.0 and Richfaces 4.0 not yet addressed this issue, what is the process to file RFC?

                         

                        There's a public JIRA issue created for it here: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1060 The spec lead has just indicated he's open to this.

                         

                        Can richfaces guys able to fix this issue with enhanced functionality with a4j components?

                         

                        They should speak for themselves of course, but earlier in this thread they have indicated not being in favor of fixing it, since staying true to the spec is quite important.

                        • 24. Re: Validation and refresh problems...
                          marcelkolsteren

                          Finally, JSF contains a fix for this problem, which is part of JSF 2.2. See http://jsflive.wordpress.com/2013/06/20/jsf-22-reset-values/.

                          1 2 Previous Next