Using Ionic Framework's $ionicLoading for Displaying Images and Messages

Troy Miles

August 14th, 2015

Sometimes your Ionic app needs to tell the user something really important. It might be so important that you want to be sure they see it before your app does anything else. For this you can usually use an Ionic popup. Popups are a nice, clean way to do something similar to the browser's alert, with none of its bad parts.

But popups have their limitations. Their design isn't very flexible. It has a title region on the top, a message region in the middle and a button region at the bottom, all on a nice white canvas, centered in the middle of the display. If you want something different, such as no buttons, no white background, just a dark screen with a message and a picture, then a popup is not for you. What can you use instead? In this post you will learn how to use Ionic's loading overlay in combination with its gestures to build an alternative modal to the popup, which is more flexible in its design.

The Ionic loading overlay usually just shows a line of text or an ionic or some combination of the two. It is meant to let the user know that the app is loading in a resource. But like many things in Ionic it has a flexible design which allows us to use it for a slightly different purpose. The template property of the overlay can hold pretty much any HTML we give it.

For our example app we will build upon the Ionic sidemenu starter template. We don't actually need to add much code to the starter template (we will use beta 14 of Ionic). First, we need to add a few references to the playlist controller. We need the Angular $timeout and the Ionic $ionicLoading and $ionicGesture, so we add their names to the parameters. We also add a variable, showingOverlay, which tells us if the overlay is currently being displayed and set it to false.

if (!showingOverlay) {
   showingOverlay = true;
   console.log("First Pass Through - show the overlay");
   $ionicLoading.show({
       template: '
<h2>A message from cat central</h2>
<img src="img/cat.jpg" alt="" width="256" height="256" />
<div>Stop playing angry birds and feed me.</div>
',
       content: 'Loading',
       animation: 'fade-in',
       showBackdrop: true,
       maxWidth: 300,
       showDelay: 0
   });
}

To display the loading overlay we call its show method. In the options that we pass to it, we set the template to the HTML we wish to display. In our case we include an image tag that points to a picture in our 'img' directory. If you'd like, you can use the templateUrl property instead of the template property. Don't forget to set the maxWidth property to something reasonable. It must be big enough to hold your content but not too big. You can also set other properties to your liking. In the example I've set the showBackdrop to true and the showDelay to zero.

Now that we have our overlay displaying to the user how do we get rid of it? Good question. $ionicLoading blocks users from interacting with the page until we want them to. In order to interact with the overlay, we will have to hook it with a gesture event.

Ionic comes with a complete set of gesture events for mobile devices. Most of the time you don't need to use them directly since Ionic widgets do that work for you, but in this example we will need to dig a bit deeper. When the $ionicLoading overlay is displayed it has no id but it does have a class of 'loading'. Once we find it, we can listen for the user to tap it, then dismiss the overlay and unbind the event.

$timeout(function () {
   if (showingOverlay) {
       // we don't need anything fancy here, we use the DOM's query selector to find the loading div
       var element = angular.element(document.querySelector('.loading')),
       // and then we hook the
           tapGesture = $ionicGesture.on('tap', function (evt) {
               console.log("TAP RECEIVED!!!");
               $ionicLoading.hide();
               $ionicGesture.off(tapGesture, 'tap');
               showingOverlay = false;
           }, element);
   }
}, 50);

Why have we wrapped the code in an Angular $timeout? We wrap the code in a $timeout because if we look for the overlay on the page immediately, it won't be there. The DOM won't have a chance to render it until our code has given control back to the browser. So we place the code in a timeout which lets the browser render the overlay. Once the timeout has elapsed, we can find overlay element on the page. Also note, we don't use jQuery, and Angular doesn't have a way to find an element by class or id. We instead use the document.querySelector method, which is in all of the devices which Ionic supports.

Once the user has tapped the overlay, we need to do some clean up. First, we hide the overlay. Then we turn off the tap event. And finally we set the flag saying whether or not we are displaying the overlay back to false.

To be honest this code really belongs in a directive and this is something I will probably do later. But it works and it neatly solves an issue I was having in my current project. If you want to check out the code for yourself it is on my GitHub repo at: https://github.com/Rockncoder/loading.

About the author

Troy Miles, aka the Rockncoder, began writing games in assembly language for early computers like the Apple II, Vic20, C64, and the IBM PC over 35 years ago. Currently he fills his days writing web apps for a Southern California based automotive valuation and information company. Nights and weekends he can usually be found writing cool apps for mobile and web or teaching other developers how to do so. He likes to post interesting code nuggets on his blog: http://therockncoder.com and videos on his YouTube channel: https://www.youtube.com/user/rockncoder. He can be reached at rockncoder@gmail.com