Show Loader on Ajax Call in jQuery Mobile

Written by on April 7, 2015

Show Loader on Ajax Call in jQuery Mobile

The loader widget handles the task of displaying the loading dialog when jQuery Mobile pulls in content via Ajax. It can also be displayed manually for custom loading actions but, what can we do if we want to show it when we initiate $.ajax call? Or how can we do it during the page transition process.

Note: If this tutorial was helpful, you need further clarification, something is not working or you have a request for another Ionic post? Furthermore, leave me a comment below if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com. Thanks and have a nice day!

Before we start we need to discuss one unlikely jQuery Mobile feature, basically you can’t manually trigger jQuery Mobile Ajax loader on web-kit browsers, at least not that easy. For some reason, you can only trigger it after a small delay, usually inside a setTimeout function. Because of this my examples will use a custom cross-platform loading function:

function loading(showOrHide) {
    setTimeout(function(){
        $.mobile.loading(showOrHide);
    }, 1); 
}

Here’s a difference:



Update: If you can't see a working example that probably means plnkr.co is down ... again. Also, funny thing, jQuery Mobile Ajax loaders will work correctly on web-kit browsers when viewed inside an iFrame. At the same time, animation will work purely so I advise you to try these examples locally.

Ajax loader is not working in the first example (web-kit browsers only), at a same time it works in a second example.

Example 1

In this example, I will show you how to enable Ajax loader globally, it will automatically work each time you initiate an $.ajax call.

$(document).on({
    ajaxSend: function () { loading('show'); },
    ajaxStart: function () { loading('show'); },
    ajaxStop: function () { loading('hide'); },
    ajaxError: function () { loading('hide'); }
});

function loading(showOrHide) {
    setTimeout(function(){
        $.mobile.loading(showOrHide);
    }, 1); 
}

Example 2

The second example will show you how to do this during the page transition period, while a page1 is transitioning to a page2. For this occasion, we will need to customize function loading.

<!DOCTYPE html>
<html>
<head>
    <title>jQM Complex Demo</title>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi"/>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script>    
    <script src="script.js"></script>       
</head>
<body>
    <div data-role="page" id="index">
        <div data-theme="a" data-role="header">
            <h3>
                First Page
            </h3>
            <a href="#second" class="ui-btn-right">Next</a>
        </div>
        <div data-role="content">
        </div>
        <div data-theme="a" data-role="footer" data-position="fixed">
        </div>
    </div>    
    <div data-role="page" id="second">
        <div data-theme="a" data-role="header">
            <h3>
                First Page
            </h3>
            <a href="#index" class="ui-btn-left">Back</a>
        </div>
        <div data-role="content">
        </div>
        <div data-theme="a" data-role="footer" data-position="fixed">
        </div>
    </div>     
</body>
</html>   
$(document).on('pagebeforecreate', '[data-role="page"]', function() {
  loading('show', 1);
});

$(document).on('pageshow', '[data-role="page"]', function() {
  loading('hide', 1000);
});

function loading(showOrHide, delay) {
  setTimeout(function() {
    $.mobile.loading(showOrHide);
  }, delay);
}

If you want to see how this example works just change the page in below example:

Who Am I?

Between working as a senior Java developer in one of the largest insurance companies in the world and traveling, in my free time, I work as a professional mobile development adviser. I'm also a major jQuery Mobile supporter back at StackOverflow and a forum moderator at the official Ionic Framework forum.



Categories

12 thoughts on “Show Loader on Ajax Call in jQuery Mobile”

  1. First, brilliant Blog, helped a lot during my mobile coding life so far, THANK YOU!

    For Example 1, it should be “loading(‘show’);” instead of “loading(show);”

    For Example 2, If I use single page structure, do I still need this setting ?

    Also, I think setTimeout(fn(), 0) is enough.

  2. That was an awesome post.
    Please I have a jquery mobile app that reads rss feeds. But the problem is that before the feeds are shown, an empty list elements are displayed for 3sec before the feeds are marked up. I want to rather see an ajax loader before the feeds.
    Please any help

        • 1. First update your jQuery Mobile 🙂 you’re using almost 5 year old version, plus jQuery Mobile js file included with jsFiddle is not matching jQuery Mobile CSS file

          2. There’s a simple solution for your list element problem. Add li elements during listEntries function call, not before.

          Here’s what’s happening in your case:

          a) Listview is filled with 20 li elements
          b) Application is creating a REST call to retrieve blog posts (this step is creating a several sec delay)
          c) Listview elements are filled with retrieved data

          Your problem is delay made by point b. You can skip it of you combine point a and c together, after a successful REST call.

          • Thanks very much for your quick reply….I have updated the jquery, jqm, and css files to the latest versions. When I added the li elements during the listEntries function call, as you stated in point 2 above, which was called inside the getOnlineContent function in a query string, the result is that the entries are no more listed, only the content is shown with unstyled css. I tried calling it also in where the getOnlineContent was called but after it, and it was the same results. ie no entries and unstyled content.

          • Yh sorry for that…Now it displayed the list, but the jquery mobile style that applies to listview content doesn’t work anymore. The list just appeared as default bullet list… and the links inside the li are also unstyled. I checked that jquerymobile.css was loaded correctly. I don’t know what went wrong.

            Thanks…

          • My problem is strange in the sense that, when I start to search in the list view using the filter, the list is rendered normally with the styles. But when the page loads, the styles doesn’t apply straight away. That is after I made those changes…

          • I would advise you to sit and learn jQuery Mobile a bit first though I’ll tell you what to do.

            First read these articles:

            http://www.gajotres.net/how-jquery-mobile-page-handling-affects-javascript-executions/
            http://www.gajotres.net/document-onpageinit-vs-document-ready/
            http://www.gajotres.net/jquery-mobile-and-how-to-enhance-the-markup-of-dynamically-added-content/

            Then decide what to do:

            1. Use your JavaScript code during pagecreate event (read second article to learn about jQuery Mobile page events)
            2. Manually trigger markup enhancement of listview component (its described in the third link)

Leave a Reply