5 Replies Latest reply on Nov 3, 2008 7:27 AM by justinmbirch

    A4J:commandButton not re-submitting

    justinmbirch

      Hi,

      I have successfully built a composite component which is composed in the java component rather than an xhtml template (needs to be completely dynamic).

      Upshot is that a dev can simply put <gls:Search ..attrs../> on their page to get a complete panel which provides search capabilities.

      OK, enough history.

      My problem is that I want to use a <a4j:commandButton> to submit the form so we can rerender only the component the search is directed at.

      In the Search component initialisition code i have

      HtmlAjaxCommandButton button = ( HtmlAjaxCommandButton )context.getApplication().createComponent( HtmlAjaxCommandButton.COMPONENT_TYPE );
      button.setId( "searchButton" );
      button.setValue( "Search" );
      button.setOnclick( (String )getAttributes().get( "onSearchClick" ) ); //javascript to run when clicked
      button.setOncomplete( (String )getAttributes().get( "onSearchComplete" ) ); //javascript to run after complete
      button.setAction( app.createMethodBinding( "#{" + backingBean + ".submitSearch}", null ) );


      This button only works once...and I'm complete stumped.

      I've tried using <a4j:form/> with and without ajaxSubmit, <a4j:region/> and several other approaches with no luck.

      Writing the <a4j:commandButton> as a child <gls:Search><a4j:commandButton .../></gls:Search> on a jsp/xhtml page and calling .click() using javascript works fine everytime.

      Anyone have any idea why the a4j button isn't submitting after subsequent keypresses when it is added programmatically ?

      Cheers, Justin

        • 1. Re: A4J:commandButton not re-submitting
          nbelaevski

          Justin,

          Can you please post some more details: search component code, especially initialization part?

          • 2. Re: A4J:commandButton not re-submitting
            justinmbirch

            Hi, sorry this reply has taken so long, been away from my desk for a few days.


            I do not have a simple use case for this problem so unfortunately I'll have to cobble it together.
            The Search component is included in a .tld and a facelets .xml descriptor as you'd expect

            Some code snippets...I've removed the comments to shorten the post where appropriate

            Search extends javax.faces.component.html.HTMLPanelGroup
            /** signature of the initialise method. This is called from SearchRenderer.encodeEnd */
            public void initialise() {
            if( !initialised ){

            ...

            HtmlAjaxCommandButton button = ( HtmlAjaxCommandButton )context.getApplication().createComponent( HtmlAjaxCommandButton.COMPONENT_TYPE );
            button.setId( "searchButton" );
            button.setValue( "Search" );
            button.setOnclick( (String )getAttributes().get( "onSearchClick" ) ); //javascript to run when clicked
            button.setOncomplete( (String )getAttributes().get( "onSearchComplete" ) ); //javascript to run after complete
            button.setAction( app.createMethodBinding( "#{" + backingBean + ".submitSearch}", null ) );

            //The HTMLAjaxCommandButton as described above is added to a HTMLPanelGrid
            HtmlPanelGrid buttonGrid = ( HtmlPanelGrid )app.createComponent( HtmlPanelGrid.COMPONENT_TYPE );
            buttonGrid.setId( "buttonGrid" );
            buttonGrid.setColumns( 2 );
            buttonGrid.setWidth( "100%" );

            buttonGrid.getChildren().add( anotherPanelContainingContent );
            buttonGrid.getChildren().add( button );

            //The HTMLPanelGrid is a direct child of this
            getChildren.add( buttonGrid );

            //other parts of panel are added below
            ...
            }
            }
            /** Restore initialised from state */
            public void restoreState( FacesContext context, Object state ) {
            Object[] store = (Object[])state;
            initialised = (Boolean)store[0];
            super.restoreState( context, store[1] );
            }
            /** Save initialised in state */
            public Object saveState( FacesContext context ) {
            Object[] state = new Object[2];
            state[0] = Boolean.valueOf( initialised );
            state[1] = super.saveState( context );
            return state;
            }
            }


            SearchRenderer

            public class SearchRenderer extends org.apache.myfaces.renderkit.HtmlGroupRenderer {
            /** Initialise the component, in this case Search */
            public void encodeEnd( FacesContext context, UIComponent component ) throws IOException {
            ((Search)component).initialise();
            super.encodeEnd( context, component );
            }
            }


            .jsp

            ...
            <!-- include -->
            <%@ taglib prefix="gls" uri="/WEB-INF/glsettle.tld"%>
            ...
            <!-- usage -->
            <gls:search id="search" backingBean="#{myBean}" />
            ...


            Hope this helps

            Cheers, Justin

            • 3. Re: A4J:commandButton not re-submitting
              justinmbirch

              FYI: Enviroment

              OC4J (JDeveloper Embedded) 10.1.3.1
              RF 3.1.6
              JSF 1.1
              Tested with JRE 1.5,1.6

              • 4. Re: A4J:commandButton not re-submitting
                nbelaevski

                Justin,

                Still no idea :( Could you please prepare small demo project, upload it somewhere (e.g. to Sendspace) and drop download link here?

                • 5. Re: A4J:commandButton not re-submitting
                  justinmbirch

                  During coding of a test case for this issue I found the problem. It was caused by one of our own components atempting to write text into the html TITLE tag to decorate with date and other info.

                  in JSP page
                  <TITLE Page <taglib:DecoratedTitle /></TITLE>
                  


                  import javax.faces.webapp.UIComponentTag;
                  
                  public class DecoratedTitleTag extends UIComponentTag
                  {
                   public String getComponentType(){ return "DecoratedTitle"; }
                  
                   public String getRendererType(){ return null; }
                  }
                  


                  import java.io.IOException;
                  
                  import javax.faces.component.UIOutput;
                  import javax.faces.context.FacesContext;
                  import javax.faces.context.ResponseWriter;
                  
                  
                  public class DecoratedTitle extends UIOutput
                  {
                   public void encodeBegin(FacesContext context)
                   {
                   try {
                   ResponseWriter writer = context.getResponseWriter();
                   writer.writeText( "some text", null);
                   }
                   catch ( IOException e ) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();
                   }
                   }
                  }
                  


                  Unfortunately UIComponentTag.findComponent would always find AjaxViewRoot and write the text directly into the output stream...I expect this damages the various scripts and js that richfaces ajax code inserts.

                  Obviously not adding the tag fixes my problem temporarily; I submit this explanation in the hope that someone may be able to elaborate on why this problem occurs in case it is a bug in RichFaces/A4J