<!DOCTYPE html>
<html>

  <head>
    <link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <link data-require="font-awesome@*" data-semver="4.1.0" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css" />
    <script data-require="angular.js@*" data-semver="1.2.14" src="https://code.angularjs.org/1.2.14/angular.js"></script>
    <script data-require="angular-route@1.2.14" data-semver="1.2.14" src="https://code.angularjs.org/1.2.14/angular-route.js"></script>
    <script src="app.js"></script>
    <script src="slowCtrl.js"></script>
    <script src="slowDataService.js"></script>
    <script src="routeLoadingIndicator.js"></script>
  </head>

  <body ng-app="route-change-loader">
    <div class="container">
      <div class="masthead">
        <ul class="nav nav-tabs">
          <li>
            <a href="#/default">Default</a>
          </li>
          <li>
            <a href="#/route1">Slow Loading Controller</a>
          </li>
        </ul>
      </div>
      <!-- Jumbotron -->
      <div class="row">
        <route-loading-indicator></route-loading-indicator>
        <div ng-if="!isRouteLoading" class="col-lg-12" ng-view=""></div>
      </div>
      <!-- Site footer -->
      <div class="footer">
        <p>by                     <a href="http://www.technofattie.com">Techno Fattie</a>
        </p>
      </div>
    </div>
  </body>

</html>
(function(){
  var app = angular.module('route-change-loader', ['ngRoute']);

  var slowResolve = function(slowDataService){
    return slowDataService.getContacts();
  };
  slowResolve.$inject = ['slowDataService'];

  app.config(['$routeProvider', function($routeProvider){
    
    $routeProvider.when('/route1', {
      templateUrl:'route1.html',
      controller:'slowCtrl',
      controllerAs:'ctrl',
      resolve:{
        contacts:slowResolve
      }
    }).otherwise({
      templateUrl:'default.html'
    });
    
  }]);

}());
<h1>Click on the tabs to change routes</h1>
<h1>{{ctrl.message}}</h1>
<table class="table table-striped">
  <thead>
    <tr>
      <th>Name</th>
      <th>Blog</th>
      <th>Twitter</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat='contact in ctrl.contacts'>
      <td>{{contact.name}}</td>
      <td>{{contact.blog}}</td>
      <td>{{contact.twitter}}</td>
    </tr>
  </tbody>
</table>
(function(app){
  
  var SlowDataService = function($timeout){
    this.$timeout = $timeout;
  };
  SlowDataService.$inject = ['$timeout'];
  
  angular.extend(SlowDataService.prototype, {
    contacts:[{
      name:'Todd Moto',
      blog:'http://toddmotto.com/',
      twitter:'@toddmotto'
    },{
      name:'Jeremy Likness',
      blog:'http://csharperimage.jeremylikness.com/',
      twitter:'@jeremylikness'
    },{
      name:'John Papa',
      blog:'http://www.johnpapa.net/',
      twitter:'@John_Papa'
    },{
      name:'Josh Carroll',
      blog:'http://www.technofattie.com/',
      twitter:'@jwcarroll'
    }],
    getContacts:function(){
      var _this = this;
      return this.$timeout(function(){
        return angular.copy(_this.contacts);
      }, 2000);
    }
  });
  
  app.service('slowDataService', SlowDataService);
  
}(angular.module('route-change-loader')));
(function(app) {
  var SlowCtrl = function(contacts) {
    this.contacts = contacts;
  };

  SlowCtrl.$inject = ['contacts'];

  angular.extend(SlowCtrl.prototype, {
    message:'Look Mom, No Lag!',
    contacts: []
  });
  
  app.controller('slowCtrl', SlowCtrl);
  
}(angular.module('route-change-loader')));
(function(app) {

  var routeLoadingIndicator = function($rootScope) {
    return {
      restrict: 'E',
      template: "<div class='col-lg-12' ng-if='isRouteLoading'><h1>Loading <i class='fa fa-cog fa-spin'></i></h1></div>",
      link: function(scope, elem, attrs) {
        scope.isRouteLoading = false;

        $rootScope.$on('$routeChangeStart', function() {
          scope.isRouteLoading = true;
        });

        $rootScope.$on('$routeChangeSuccess', function() {
          scope.isRouteLoading = false;
        });
      }
    };
  };
  routeLoadingIndicator.$inject = ['$rootScope'];

  app.directive('routeLoadingIndicator', routeLoadingIndicator);

}(angular.module('route-change-loader')));