Category

Category: AngularJS

AngularJS – Show route only after all Ajax requests are resolved

Have you tried creating an app that load contents via AJAX?, I am sure you later find it annoying that your page template is loaded faster than your Ajax Request causing your users to see an incomplete page. In this tutorial I will show you how you can tell AngularJS to wait for the Ajax Request to complete before displaying your page template to the screen. This tutorial also covers resolving promises with Dynamically generated routes.

Using “resolve”

First define a route with resolve attribute like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var app = angular.module('tutorialWebApp', ['ngRoute']);
app.config(function ($routeProvider, $locationProvider) {
    $routeProvider 
    .when("/page-title", {
        templateUrl: "partials/page-title.php",
        controller: "PageCtrl",
        resolve: {
            pageData: function($http, $route){
                return $http.get('http://example.com/posts').then(function(response){
                    return response.data;
                })
            }
        }
    })
});

Notice that the controller definition contains a resolve object which declares things which should be available to the controller constructor.

The resolve.pageData function is responsible for returning a promise. All of the promises are collected and the route change is delayed until after all of the promises are resolved.

Dynamic Routes

We can also make the resolve attribute work with dynamically generated routes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var app = angular.module('tutorialWebApp', ['ngRoute']);
app.config(function ($routeProvider, $locationProvider) {
    $routeProvider 
    .when("page-list/:slug", {
        templateUrl: "partials/page-single-title.php",
        controller: "PageCtrl",
        resolve: {         
            pageData: function($http, $route){
                return $http.get('http://example.com/posts/?name='+$route.current.params.slug).then(function(response){
                    return response.data;
                })
            }
        }
    })
});

Accessing Data in a Controller

You can simply access the data result like this:

1
2
3
app.controller('PageSingleCtrl', function( $scope, pageData ) {
    $scope.post = pageData;
});

AngularJS – Show a loading image on HTTP Requests

Directive

Add this directive to your app:

1
2
3
4
5
6
7
8
9
10
11
12
13
var app = angular.module('tutorialWebApp', ['ngRoute']);
app.directive('loading', function () {
    return {
        restrict: 'E',
        replace:true,
        template: '<p><img src="img/loading.gif"/></p>', // Define a template where the image will be initially loaded while waiting for the ajax request to complete
        link: function (scope, element, attr) {
            scope.$watch('loading', function (val) {
                val = val ? $(element).show() : $(element).hide();  // Show or Hide the loading image  
            });
        }
    }
});

Usage: Add this code to before $http.get: $scope.loading = true; then $scope.loading = false; on ajax success

Example

Example usage in a controller:

1
2
3
4
5
6
7
app.controller('PageCtrl', function ( $scope, $http, $routeParams ) {
    $scope.loading = true; // Show loading image
    $http.get('http://example.com/posts').success(function(data){
        $scope.posts = data;
        $scope.loading = false; // hide loading image on ajax success
    });
});