Execute JavaScript after every JSF ajax postback

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.


Solution 1:

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:

  • How to re-execute javascript function after form reRender?