Tiago Vieira Dos Santos Tiago Vieira Dos Santos - 5 months ago 35
Ajax Question

How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?

I need to execute a JSF managed bean action method using ajax during HTML DOM

load
event, similar to jQuery's
$(document).ready(function() { $.ajax(...) })
. I can only use the JavaScript generated by JSF in this project. Is there a way to do it in native JSF? Which event can I use or which JSF ajax function can I use?

I'm using JSF 2.0, Facelets and PrimeFaces.

Answer

Several ways.

  1. Use the "hidden form" trick (actually, "hack" is given the ugliness a better wording).

    <h:form id="form" style="display:none;">
        <h:commandButton id="button" action="#{bean.action}">
            <f:ajax render=":results" />
        </h:commandButton>
    </h:form>
    <h:panelGroup id="results">
        ...
    </h:panelGroup>
    

    You can invoke it in JS as below:

    document.getElementById("form:button").onclick();
    

    Note the importance of triggering onclick() instead of click() in case of <h:commandButton>. The onclick() immediately invokes the onclick function while the click() only triggers the "click" event on the element, which is not supported in IE. If you were using a <h:commandLink>, you can safely use click() instead.

    To invoke it during load event, consider putting it in <h:outputScript target="body">. The target="body" automatically puts the <script> in end of <body>, thus a $(document).ready() wrapper is unnecessary.

    <h:outputScript target="body">
        document.getElementById("form:button").onclick();
    </h:outputScript>
    

  2. As you're already using PrimeFaces, just use its <p:remoteCommand>.

    <h:form>
        <p:remoteCommand name="commandName" action="#{bean.action}" update=":results" />
    </h:form>
    <h:panelGroup id="results">
        ...
    </h:panelGroup>
    

    You can invoke it in JS as below:

    commandName();
    

    This however doesn't use JSF native jsf.ajax.request(), instead it uses PrimeFaces native jQuery (you know, PrimeFaces is a JSF component library on top of jQuery/UI).

    To invoke it during load event, set autoRun="true".

    <p:remoteCommand ... autoRun="true" />
    

  3. Create a custom UIComponent which extends UICommand and generates the necessary JSF native jsf.ajax.request() call. You're then in essence reinventing the <p:remoteCommand> to use native JSF ajax instead of jQuery. The JSF utility library OmniFaces has a <o:commandScript> component which does exactly that. See also the showcase and the source code.

    <h:form>
        <o:commandScript name="commandName" action="#{bean.action}" render=":results" />
    </h:form>
    <h:panelGroup id="results">
        ...
    </h:panelGroup>
    

    You can invoke it in JS as below:

    commandName();
    

    To invoke it during load event, set autorun="true".

    <o:commandScript ... autorun="true" />
    

  4. Upgrade to JSF 2.3 and use the native <h:commandScript> component. It's available since 2.3.0-m06. The syntax is exactly the same as above <o:commandScript>. Just replace o: by h:.

Comments