Reputation: 5977
I am trying for hours, but with no luck at all. I have an angularjs application where i want to present the user with a loading spinner as long as the page is not fully loaded (rendered). Especially between state changes, because the click is registered, but nothing is happening right away. Thus the user is getting no feedback if it is actually loading or not. My application is requesting some data through ajax when the controller is getting executed. I have already tried different solutions:
Using $stateChangeStart
and $viewContentLoaded
. This approach does work fine if the views are loaded for the first time, but fires too early for every subsequent state change. This has to do with the caching of templates. Every time the viewContentLoaded is fired the template is cached.
Using a directive with $timeout
. This does work very well on the first load-up if i attach it to the body
of my html document. But since i am using nested views/controllers the directive is not called again when i switch between states. It is once again fired to early when i attach the directive to the ui-view
element.
Are there any alternatives? Am i doing something wrong? Is it even possible?
Thanks
Upvotes: 0
Views: 2443
Reputation:
For someone.
<div style="visibility: hidden;">
{{MyVarAfterLoad = true}}
</div>
Upvotes: 0
Reputation: 7926
Have a look at angular-block-ui, which is a module that takes care of displaying a loading indicator. Blocking can be done on the whole page or on individual elements. Behind the scenes it monitors http requests and determines if a block should be active (it ignores cached http requests).
Upvotes: 0
Reputation: 28638
Have you tried using the resolve
object?
You can use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.
https://github.com/angular-ui/ui-router/wiki#resolve
Using resolve
allows you to fetch your data before the controller is initialized. That way when your controller executes and $viewContentLoaded
is fired you can be sure that your data is available:
$stateProvider.state('myState', {
templateUrl: 'template.html',
controller: function($scope, myData){
$scope.myData = myData;
},
resolve:{
myData: function($http){
return $http({method: 'GET', url: '/myUrl'})
.then (function (data) {
return doSomeStuffFirst(data);
}
);
}
}
});
I bet when using resolve
and your first option (using $routeChangeStart
and $viewContentLoaded
to set and remove your spinner) things will work a lot better than it does now.
Upvotes: 1
Reputation: 493
Create a div in your webapp where you want the spinner to display.
use an ng-show="loading"
Before your request set $scope.loading = true; then create an AngularJS promise which (using a .then() or .finally()) and in this .finally() put $scope.loading = false;
This way it shows your spinner while it's loading and when it's finally done it sets it to false which keeps it from showing.
Upvotes: 0