I'm trying to toggle (hide/show) a loading gif on every new route, so my logic would be:
This is my code:
//ANGULAR
app.run(function($rootScope) {
$rootScope.layout = {};
$rootScope.layout.loading = false;
$rootScope.$on('$routeChangeStart', function() {
//show loading gif
$rootScope.layout.loading = true;
});
$rootScope.$on('$routeChangeSuccess', function() {
//hide loading gif
$rootScope.layout.loading = false;
});
$rootScope.$on('$routeChangeError', function() {
//hide loading gif
alert('wtff');
$rootScope.layout.loading = false;
});
});
//HTML
<img src="img/loading.gif" ng-hide="!layout.loading"/>
it is strange cause this works for 3/4 routes changed then it stop working while changing routes :O
what it could be?
HERE IS A LIVE EXAMPLE thanks to @Rob Sedgwick : http://plnkr.co/edit/ZpkgRhEAoUGlnXjbLb8b
Short answer: the $rootScope.layout.loading
changed as expected. But if the templates are loaded the browser has no time to make the changes visible.
Long answer: if you put console.log
outputs in your $on
listeners you will see, that a $routeChangeStart
event fires, the template is loaded and after that $routeChangeSuccess
fires. Under the hood the following happens:
$routeChangeStart
fires$rootScope.layout.loading
becomes true
a little bit later (the xhr request returns)
$routeChangeSuccess
fires$rootScope.layout.loading
becomes false
what happens if the tmeplates are cached:
- $routeChangeStart
fires
- $rootScope.layout.loading
becomes true
- $routeChangeSuccess
fires
- $rootScope.layout.loading
becomes false
- the DOM is updated (but this is the same state as before)
As you can see the browser can not render the new state because a script is running that is not interrupted to give the browser time to render the DOM. If the template is not yet loaded, the ajax requests stops the script execution and give's the browser time to render the DOM.
How to fix this?
You can use a timeout
that give's the browser time to update the DOM:
$rootScope.$on('$routeChangeSuccess', function () {
console.log('$routeChangeSuccess');
//hide loading gif
$timeout(function(){
$rootScope.layout.loading = false;
}, 200);
});
Here is your plunkr with this solution: http://plnkr.co/edit/MkREo0Xpz5SUWg0lFCdu?p=preview
( A little too much to put in a comment )
I set the code up and saw that the loading variable was not updated each time and was due to the template caching, I guess the 'RouteChange' is not triggered.
Disabling the template caching will let your code run each time ..
app.run(function($rootScope, $location, $anchorScroll, $routeParams,$templateCache) {
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With