Search code examples
ajaxjsfviewaction

Something like f ajax within f viewaction?


I need to show loading image while execute request when execute a f:viewaction, this sound as put f:ajax within f:viewaction, but this is impossible.

<ui:define name="metadata">
    <f:metadata>
        <f:viewAction
            action="#{subscriptionManagementMB.loadSubscriptionManagement()}" />
    </f:metadata>
</ui:define>

Solution

  • There's a conceptual thinking mistake here. You can't show an image as long as the page with the image isn't loaded (whatever that image represents is irrelevant to the problem). In order to show an image, you need to make sure that the page with the image is fully loaded first. Only when the page with the image is fully loaded, then you can invoke the desired business action.

    The <f:viewAction> is insuitable for this. The common approach is to let JavaScript trigger a server side action when end of <body> is reached, or during document ready/complete event, or during window load event. The exact answer really depends on the libraries you've at hands. The code can be insanely simplified when you've PrimeFaces and/or jQuery at hand.

    Let's assume "plain vanilla" JSF/JS, here's a hacky way how to achieve the requirement:

    <h:body>
        <h:panelGroup id="content">
            <h:graphicImage name="loading.gif" rendered="#{not bean.loaded}" />
    
            <ui:fragment rendered="#{bean.loaded}">
                ... (put your content here)
            </ui:fragment>
        </h:panelGroup>
    
        <h:form id="form" style="display:none;">
            <h:commandButton id="button" action="#{bean.onload}">
                <f:ajax render=":content" />
            </h:commandButton>
        </h:form>
    
        <h:outputScript target="body">
            document.getElementById("form:button").onclick();
        </h:outputScript>
    </h:body>
    

    The image shows the loading image. The form, which is hidden using CSS display:none, holds an ajax command button which updates the content. The script with target="body" will be relocated to end of <body> and invoke the hidden ajax command button when page is loaded.

    See also: