I use <div ng-view></div>
on web page.
When I click link in block <div>
is loaded HTML template was set in routeProvider
. Also together is done request AJAX that returns data that was loaded template.
Now problem is that after click I get HTML template with empty form, still is working AJAX request. After some seconds form HTML is fiiled data from AJAX.
How I can do preloader to page for directory ng-view
?
It seems that there are some similar questions here:
- Angularjs loading screen on ajax request
- Angular JS loading screen and page animation.
Also, there a bunch of modules to work with loading animation at http://ngmodules.org. For example, these:
- https://github.com/cgross/angular-busy
- https://github.com/chieffancypants/angular-loading-bar (I use this one in my apps)
- https://github.com/McNull/angular-block-ui and other.
UPD:
I've written a simple solution based on how the angular-loading-bar works. I didn't test it with ng-view, but it seams to work with ui-view. It is not a final solution and have to be polished.
angular.module('ui')
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('LoadingListener');
}])
.factory('LoadingListener', [ '$q', '$rootScope', function($q, $rootScope) {
var reqsActive = 0;
function onResponse() {
reqsActive--;
if (reqsActive === 0) {
$rootScope.$broadcast('loading:completed');
}
}
return {
'request': function(config) {
if (reqsActive === 0) {
$rootScope.$broadcast('loading:started');
}
reqsActive++;
return config;
},
'response': function(response) {
if (!response || !response.config) {
return response;
}
onResponse();
return response;
},
'responseError': function(rejection) {
if (!rejection || !rejection.config) {
return $q.reject(rejection);
}
onResponse();
return $q.reject(rejection);
},
isLoadingActive : function() {
return reqsActive === 0;
}
};
}])
.directive('loadingListener', [ '$rootScope', 'LoadingListener', function($rootScope, LoadingListener) {
var tpl = '<div class="loading-indicator" style="position: absolute; height: 100%; width: 100%; background-color: #fff; z-index: 1000">Loading...</div>';
return {
restrict: 'CA',
link: function linkFn(scope, elem, attr) {
var indicator = angular.element(tpl);
elem.prepend(indicator);
elem.css('position', 'relative');
if (!LoadingListener.isLoadingActive()) {
indicator.css('display', 'none');
}
$rootScope.$on('loading:started', function () {
indicator.css('display', 'block');
});
$rootScope.$on('loading:completed', function () {
indicator.css('display', 'none');
});
}
};
}]);
It can be used like this:
<section class="content ui-view" loading-listener></section>
You can try something like this(simplest solution):
Set your loader animation/picture:<div class="loader" ng-show="isLoading"></div>
On div
element add click event:
- Then AJAX request success set
isLoading=true
Download javascript and css files from PACE Loader.
Playing around with pace loader using ng-views . Hope this helps someone trying to use PACE.JS with Angular. In this example I am using ng-router to navigate between views.
app.js
var animateApp = angular.module('route-change-loader', ['ngRoute']);
var slowResolve = function(slowDataService){
return slowDataService.getContacts();
};
slowResolve.$inject = ['slowDataService'];
// ROUTING ===============================================
// set our routing for this application
// each route will pull in a different controller
animateApp.config(function($routeProvider) {
$routeProvider
// home page
.when('/route1', {
templateUrl: 'route1.html',
controller: 'slowCtrl',
controllerAs:'ctrl',
resolve: {
contacts:slowResolve
}
})
.otherwise({
templateUrl:'default.html'
});
});
var SlowCtrl = function(contacts) {
this.contacts = contacts;
};
SlowCtrl.$inject = ['contacts'];
angular.extend(SlowCtrl.prototype, {
message:'Look Mom, No Lag!',
contacts: []
});
animateApp.controller('slowCtrl', SlowCtrl);
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);
}, 1000);
}
});
animateApp.service('slowDataService', SlowDataService);
index.html
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Test Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="pace.css">
<script src="http://code.angularjs.org/1.2.13/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular-route.js"></script>
<script src="app.js"></script>
<script src="pace.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 <b>Ritesh Karwa</b> </a>
</p>
</div>
</div>
</body>
</html>
default.html
<h1>Click on the tabs to change routes</h1>
route1.html
<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>