javascriptjsfjsf-2.2

jsf.ajax.addOnEvent works only if I explicitly include javax.faces:jsf.js


I am using JSF 2.2.4 with the following in head tag:

<h:outputScript library="javax.faces" name="jsf.js" />

Later I found following post and removed the above code as it will be included automatically: renaming jsf.js.jsf to jsf.js.xhtml

When I checked found that it is included automatically as said but we are getting error with a script that is put in the head of common template. The error is the script is getting the object jsf as undefined. The purpose of this script is to show a common loader for all JSF AJAX calls. The script is given below:

//To display loading indicator for all JSF f:ajax calls.
jsf.ajax.addOnEvent(function(data) {
  var ajaxstatus = data.status; // Can be "begin", "complete" and "success"
  switch (ajaxstatus) {
    case "begin": // This is called right before ajax request is been sent.
      wizShowAjaxLoader();
      break;
    case "complete": // This is called right after ajax response is received.
      wizHideAjaxLoader();
      break;
    case "success": // This is called when ajax response is successfully processed.
      // NOOP.
      break;
  }
});

I wonder why it is working when I explicitly include jsf.js. When I remove this, script is showing jsf object as undefined.


Solution

  • You need to make sure that your script is invoked after javax.faces:jsf.js is being included, for the very simple reason that jsf is only defined in JavaScript scope when the javax.faces:jsf.js has been included (and executed).

    In a nutshell, you need to make sure that the JavaScript code flow is like below:

    var jsf = ...;
    ...
    jsf.ajax.addOnEvent(...);
    

    And thus not like so:

    jsf.ajax.addOnEvent(...);
    ...
    var jsf = ...;
    

    One way of ensuring this is to include your script as <h:outputScript> in <h:body> with the target set to head.

    <h:head>
        ...
    </h:head>
    <h:body>
        <h:outputScript name="yourscript.js" target="head" />
        ...
    </h:body>
    

    JSF will ensure that it ends up in HTML head after the auto-included scripts.

    An alternative is to keep it in <h:head>, but set target to body.

    <h:head>
        ...
        <h:outputScript name="yourscript.js" target="body" />
    </h:head>
    

    JSF will ensure that it ends up in very end of HTML body, so that it's basically executed right before DOM loaded event.

    See also: