15

I have a javascript function that I would like to execute after every asynchronous postback in JSF 2.

I have done the following to ensure that every full page postback this gets executed:

jQuery(document).ready(mahFunction);

The reason I need to do this is to workaround a glitch in a third-party JSF component library so I cannot modify anything in the server render phase to do this for the component.

I am having trouble finding information on this possibly because I am using the incorrect terms. I used to be an ASP.NET developer and I refer to these terms as "full page postback" and "partial postback" where it seems other JSF developers do not use such terms.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
maple_shaft
  • 10,435
  • 6
  • 46
  • 74

1 Answers1

33

You could register it as JSF ajax callback handler by jsf.ajax.addOnEvent:

<script>
    jsf.ajax.addOnEvent(foo);
</script>

with

<script>
    function foo(data) {
        var ajaxStatus = data.status; // Can be "begin", "complete" and "success".

        switch (ajaxStatus) {
            case "begin": // Right before sending ajax request.
                // ...
                break;
            
            case "complete": // Right after receiving ajax response.
                // ...
                break;

            case "success": // When ajax response is successfully processed.
                // ...
                break;
        }
    }
</script>

where the data object has several useful XHR derived properties which is described in table 14-4 of JSF 2.0 specification (click the For Evaluation link). Here's an extract of relevance:

TABLE 14-4 Event Data Payload

    Name           Description/Value
    -------------  ----------------------------------------------------
    type           “event”
    status         One of the events specified in TABLE 14-3
    source         The DOM element that triggered the Ajax request.
    responseCode   Ajax request object ‘status’ (XMLHttpRequest.status); 
                   Not present for “begin” event;
    responseXML    The XML response (XMLHttpRequest.responseXML); 
                   Not present for “begin” event;
    responseText   The text response (XMLHttpResponse.responseTxt);
                   Not present for “begin” event;

As an alternative, a XHTML-declarative way would be to just embed the script call in a JSF component with an id and let the ajax call re-render it. The component should in turn render the script conditionally based on FacesContext#isPostback().

<h:form>
    <h:commandButton value="Submit" action="#{bean.submit}">
        <f:ajax render=":myscript">
    </h:commandButton>
</h:form>

<h:panelGroup id="myscript">
    <h:outputScript rendered="#{facesContext.postback}">foo();</h:outputScript>
</h:panelGroup>

Most component libraries have however better abstracted support for this. Since you didn't mention which one you're using so that a more suited answer can be given, here's just a random example based on PrimeFaces command button.

<p:commandButton value="Submit" action="#{bean.submit}" oncomplete="foo();" />

Refer the documentation of the component library you're using.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I am indeed using the Primefaces component library however the particular component I need does not have an oncomplete attribute. I tried both of your suggestions and neither of them caused my javascript to be called after the postback. I placed a breakpoint in Firebug to verify this. – maple_shaft Apr 19 '11 at 17:29
  • The component in question is the p:calendar and the p:inputMask. My javascript removes the theme classes from input elements within these components. This normally works fine but they are within a p:wizard and every time a partial postback occurs to navigate to the next tab the javascripts are not getting called. Would a validation error on the form prevent this javascript from being invoked? – maple_shaft Apr 19 '11 at 17:32
  • PrimeFaces may have shipped with its own JS ajax library. Note that you need to use `` instead of `` for PrimeFaces components. But why don't you just use CSS to overridde the default styles? Anyway, in your future JSF questions please specify the component library you're using and also the functional requirement. – BalusC Apr 19 '11 at 17:39
  • I suppose I could but there are several classes being applied to each input and containing span and each of these have a multitude of different styles. I fought with it for over three hours until I realized that a few lines of jQuery removed the all of the offending styles perfectly. It seems that the Primefaces team added the ability to turn off form themes in 3.0 but it is still a relatively unstable release with a lot of bugs. I would prefer to avoid that because I just got everything the way I need it except for this last remaining issue. EDIT: Ah... let me try p:ajax and I will get back. – maple_shaft Apr 19 '11 at 17:41
  • Okay, that didn't work either because the p:ajax can only be applied to components that allow you to specify client behavior which the wizard or the tab do not. I tried again to override the styles with my own class but found that no matter what I do, primefaces theme stylesheets always override MY stylesheets. If I declare my stylesheet first in the page then things get MAJORLY screwed up and I have little idea as to why. I am pretty much out of ideas here. – maple_shaft Apr 19 '11 at 18:56
  • Figured it out. The absolute only way was to inline write the overriding styles to each element, as inline styles trump all classes. Wow. Thanks for your help Balus! I was hoping that you would help me out! – maple_shaft Apr 19 '11 at 19:12