Visualforce: Integrating a pretty “loading” animation

Introduction

One of the reasons I love doing Visualforce development on Salesforce is because how easy it is to do asynchronous (ajax; javascript) requests for server-side (apex) processing. It is incredibly easy with the apex:actionFunction tag — just return null in a PageReference-returning apex method, call this method as the action in an apex:actionFunction, and do some reRendering. It works wonderfully, but it doesn’t look great. It’s missing some key visual indicators.

The Problem

A common customer request with asynchronous server-side rendering is “Can we have indication that that the page is doing something?” and similarly “How do we know when the page is done processing?” In other words, they want to see a fancy “loading” graphic while the processing is occurring until it completes.

There are two variations to solutions of this problem — one can lock all asynchronous-requesting-controls while the asynchronous request is processing. This effectively makes the asynchronous request a synchronous one, while not requiring a page refresh and maintaining the page state. The other approach allows editable controls, which inevitably allows multiple asynchronous requests to execute in parallel. Which approach you choose ultimately depends on the use case, and practically the solution should depend on how much processing has to occur and how much of the page changes as a result of the processing. The implementation of each is identical, simply differentiated by what blocks of code should be encapsulated.

The Solution

Enter apex:actionStatus. There are various blog topics in the space that give a general idea on how to do this, but I couldn’t find a great example showing this in action.

This solution is simple to implement:

  1. Include javascript at the top of the page which manages the visibility of the loading graphic and optionally the editable controls. For sample purposes, I’m going to assume we want the editable controls to be non-editable during this asynchronous request. There are other ways to control visibility than messing with style.display from the DOM. Feel free to use your favorite cross-browser javascript framework that you have integrated into your page to do this.

    The javascript involved is:

    <script type="text/javascript">
      function loading(val) {
        if (val) {
          document.getElementById('contentLoading').style.display = 'block';
          document.getElementById('contentLoaded').style.display = 'none';
        }
        else {
          document.getElementById('contentLoading').style.display = 'none';
          document.getElementById('contentLoaded').style.display = 'block';
        }
      }
    </script>
    
  2. Add an apex:status block, which will be referenced from your apex:actionFunction’s “status” attribute, and will call the above javascript.

    A sample of this is:

    <apex:actionFunction name="function" action="{!asyncMethod}" rerender="toRerender" status="loading" />
    …
    <apex:actionStatus id="loading" onstart="loading(true)" onstop="loading(false)" />
    
  3. Add the loading graphic div. A sample of this:
      <div id="contentLoading" style="display:none;">
        <div style="text-align: center;">
          <img src="/img/loading.gif" alt="Loading graphic" />
        </div>
      </div>
    
  4. Optionally encapsulate the editable controls with a div. A sample of this:
      <div id="contentLoaded">
      … controls go here …
      </div>
    

A demo of this in action:
Unable to display content. Adobe Flash is required.

This entry was tagged , , , , . Bookmark the permalink.

10 Responses to Visualforce: Integrating a pretty “loading” animation

  1. yvk431 says:

    Hi Ray,

    Thanks for the cool article. I tried to implement this but what I end up with is a gif image confined to a small portion of the page. Its not covering the editable portions of the page, its just getting displayed as a separate component.

    I wanted to have the jQuery’s blockUI effet.

    Any thought on this .

    Thanks
    yvk431

    • Ray Dehler says:

      You need to wrap the relevant controls in this loading animation. If the controls are still editable, you need to expand the content that is wrapped.

  2. suz says:

    I am having the same problem as the above poster and I don’t understand your reply. Can you explain with greater detail how to ‘wrap’ the entire page? When I wrap the entire page in the div, nothing is visible on the page.

  3. Pingback: Using the Salesforce JSON Generator for quick visualforce translations | Cloud Clod

  4. edaws says:

    THANK YOU! I spent forever trying to figure this out from various blogs but couldn’t understand what was actually going on (relationship between actionFunction and actionStatus) until I read this.

    FYI- here is a pretty useful gif generator for loading animations

  5. Phil says:

    Its even easier than above, actionStatus has its own facets

    Here’s a snippet:

    Saving…

    This won’t show up on the page except during the ajax action. You shouldn’t need the javascript from step 1. Just put everything you need inside the facet :)

    Reference: http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_actionStatus.htm

  6. Phil says:

    Er here’s attempt 2 without any :

    apex:actionStatus startStyleClass=”saveStatus” id=”savingStatus”
    apex:facet name=”start”
    img src=”{!$Resource.ajaxloader}” border=”0″/ Saving…
    /apex:facet
    /apex:actionStatus

  7. Pingback: Visualforce: Integrating a loading animation the standard way | Cloud Clod

Comments are closed.