简体   繁体   中英

Deferring angular controllers until Ajax call is completed

First of all, I have googled and searched on SO for this question. None of the answers I've seen are really satisfactory for me. I am aware of resolve & manually bootstrapping angular and neither are great solutions for us.

Essentially our app is constructed such that at the top level, we have a

<body ng-controller="applicationController">

that instantiates a bunch of stuff. Part of that is getting some data from our server and setting it so that children controllers have access to it. So the issue is sometimes the children controllers are executed before the server has responded.

We use angular UI's ui-router so we can take advantage of states. However resolve hasn't been a great solution for us because we have a bunch of routes and a user can enter the app from any of them. So far my only solutions are to create a very high level parent state and putting a resolve on that, or putting a resolve a multitude of states. Is there a way to make the ajax call before the angular controllers are run?

What about ng-include ( http://docs.angularjs.org/api/ng.directive:ngInclude )? Remove all the subcontroller stuff from your html file and put it in a template file. Now you may load some data from your server and if they all have arrived set the ng-include src.

With this solution you also have the possibility showing another template file during the loading phase.

If you don't want your content in another file you may consider writing a directive that can handle inline templates:

<script type="text/ng-template" id="my-awesome-content.html">
   ... 
</script>

If you want to delay the instantiation of your controller, you need at some point to take advantage of promises and $routeProvider .

Misko Hevery (the creator of AngularJS) answered such question here: Delaying AngularJS route change until model loaded to prevent flicker

He updated the "AngularJS getting started tutorial" to conform to that pattern; it is worth reading it.

I run into the same question a few months ago; I architected my app to follow that principle.

Basically set a url/entry point in your app that resolves the instantiation of your controllers.

If your app is accessible from other locations, redirect the call to that entry point/url; after the init stuff has been resolved, redirect to the requested url.

I upvoted both answers here because, in my opinion, the most elegant solution is a combination of both (without redirecting back and forth). The core of this problem is the fact that angular only allows synchronised dependency injection on controller arguments via the route provider. We can however wrap all our initialisation in a single service and let our main controller to be dependent on this.

See this plunker for a live demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM