6 Replies Latest reply on May 18, 2009 5:59 PM by nbelaevski

    Ajax component, phase listener and findComponent help

      Hello,

      I tried this in the Sun Forum, but I recon that there might be more know-how on this issue on this forum, so I'm trying here ;)

      I have a component that issues an Ajax Request. This request is collected by a phase-listener and then processed, however I am having difficulties finding the component that I want to re-render.

      Is there a common approach for getting hold of components from a PhaseListener ? My scenario is:

      When the user clicks and drags inside my component, I want to register the X-axis drag with a ValueChangeListener. (The component has a valueChangeListener="" attribute).

      I am able to get the X-axis drag amount sent via Axis and into the PhaseListener, but at this point I am stuck. I now need to get hold of my component, and tell it how much to move the X-axis.

      Any help is very much appreciated!

        • 1. Re: Ajax component, phase listener and findComponent help
          nbelaevski

          Hello,

          What if the component will process request and find the dependent component itself? If phase listener is the only option, then you can do

          facesContext.getViewRoot().findComponent()
          or
          facesContext.getViewRoot().invokeOnComponent()

          invokeOnComponent have a special behavior that allows this method to work with components nested inside iteration components in context of the particular iteration.


          • 2. Re: Ajax component, phase listener and findComponent help

             

            "nbelaevski" wrote:
            Hello,

            What if the component will process request and find the dependent component itself? If phase listener is the only option, then you can do
            facesContext.getViewRoot().findComponent()
            or
            facesContext.getViewRoot().invokeOnComponent()

            invokeOnComponent have a special behavior that allows this method to work with components nested inside iteration components in context of the particular iteration.


            Thank you for your response!

            I am not sure what you mean by "what if the cmponent will process request". When the user performs a mouse-drag on the component, it fires off an Ajax request:

             new Ajax.Request(url, {
             method: 'get',
             parameters: {
             "component-id": componentId,
             "item-id": itemId,
             "item-value":itemValue,
             "ajax" : ajaxStr
             }
             });
            


            Now, two things happen. The phaselistener afterPhase method is called, inside which I am able to collert the parameters from the Ajax Request, for instance like this:

            request.getParameter("item-id");
            


            If I let the phaseListener continue without any special processing, my components encodeEnd is called (decode() is never called as far as I can tell). I am not sure what the best strategy is, but for some reason I am unable to find the component in question from the PhaseListener using either call:

            Boolean foundComponent = context.getViewRoot().invokeOnComponent(context, "valueTimeChart", executeCommandButtonAction);
             UIComponent comp = context.getViewRoot().findComponent("valueTimeChart");
            


            I could always get the "item-id" from the request inside encodeEnd, and if it matches the component, use the "item-value" from the request and queue off the ValueChangeListener inside encodeEnd, however it would be a lot cleaner to do this inside a decode method IMO.

            • 3. Re: Ajax component, phase listener and findComponent help
              nbelaevski

               

              "nbelaevski" wrote:
              What if the component will process request and find the dependent component itself?

              That was the question on why do you need to do processing in phase listener and not in the component's decode(). Looks like the problem is in how you call AJAX:

              1. It is "get" not "post"
              2. JSF requires view state field to be submitted

              You can use methods from org.ajax4jsf.renderkit.AjaxRendererUtils to build AJAX request that will be processed by RF core framework.

              And I guess, component is not found because it is not present in the created view.

              • 4. Re: Ajax component, phase listener and findComponent help

                 

                "nbelaevski" wrote:
                "nbelaevski" wrote:
                What if the component will process request and find the dependent component itself?

                That was the question on why do you need to do processing in phase listener and not in the component's decode(). Looks like the problem is in how you call AJAX:

                1. It is "get" not "post"
                2. JSF requires view state field to be submitted

                You can use methods from org.ajax4jsf.renderkit.AjaxRendererUtils to build AJAX request that will be processed by RF core framework.

                And I guess, component is not found because it is not present in the created view.


                Aha, that makes a lot of sense! JSF is a "Post-centric" framework indeed. I did manage to get this working after some work, but I ended up with having do put code inside encodeEnd. I will try to use method: "post" in the Ajax request and see if that changes anything. I will also look into the AjaxRendererUtils.

                Than you very much for your response!

                • 5. Re: Ajax component, phase listener and findComponent help

                  Regarding point 2 below, is it enought to post the viewstate back inside to POST method ? I cant seem to get the decode method to fire...

                  new Ajax.Request(url, {
                   method: 'post',
                   contentType: "application/x-www-form-urlencoded",
                   parameters: {
                   "item-id": itemid,
                   "item-value":event,
                   "ajax" : options,
                   "javax.faces.ViewState": viewState.value
                   }
                  });
                  


                  "nbelaevski" wrote:
                  "nbelaevski" wrote:
                  What if the component will process request and find the dependent component itself?

                  That was the question on why do you need to do processing in phase listener and not in the component's decode(). Looks like the problem is in how you call AJAX:

                  1. It is "get" not "post"
                  2. JSF requires view state field to be submitted

                  You can use methods from org.ajax4jsf.renderkit.AjaxRendererUtils to build AJAX request that will be processed by RF core framework.

                  And I guess, component is not found because it is not present in the created view.


                  • 6. Re: Ajax component, phase listener and findComponent help
                    nbelaevski

                    Should be enough for the common request; RF AJAX requests also add AJAXREQUEST parameter; there is one more parameter for ajaxSingle components; maybe some more - please take a look at AjaxRendererUtils sources.

                    For forms, their client id is submitted - if it's absent, form children and facets aren't processed. Non-rendered elements and their children aren't processed (BTW, note that findComponent/invokeOnComponent do not handle "rendered" anyhow).

                    You can try adding PhaseTracker to the application and check which lifecycle phases are executed for the AJAX request.