Reputation: 1951
Assume i've a route on my app like /config.json
which will return an object with settings like user currency, user locale, etc.
I would like to preload all of this values as soon as possible, and only one time, while the application is going up.
The app.config()
section would be good enough i think, but i cannot access the $http service at that time. How would you approach this?
EDIT
I'm adding this attempt to provide more context.
module.factory("test", function ($http) {
// This is the service. It depends on the
// settings, which must be read with a HTTP GET.
return service = {
settings: null,
get: function(value) {
return this.settings[ value ];
}
};
});
I've tried to return a deffered service instance, i.e.
return $http.get('/config').then(function(response){
service.settings = response.data;
return service;
});
but, apparently, it's not allowed to return a deferred service.
Upvotes: 1
Views: 887
Reputation: 4185
Try using app.run()
method instead of config, you can inject there
Update: Try using a provider with cache:
app.provider('configurationsProvider', function() {
this.$get = function($http) {
if (!this.configurationsPromise){
this.configurationsPromise = $http.get('/ConfigUrl');
}
return this.configurationsPromise;
};
});
app.service('someService', function(configurations){
configuration.then(function(conf){
});
});
Update2:
Any way, you need to assume the setting loading may take some time...So you can go with the approach like this:
app.value('config', { isLoading: true })
.service('someService', ['config', function('config') {
...
this.doSomething = function() {
var someConfig = config.configValue;
}
}]);
app.run(['config', '$http', function(config, $http){
$http.get('configUrl').then(function(conf) {
_.defaults(config, conf); // or some other way to clone all the properties
config.isLoading = false;
});
});
The idea is when the settings are loading the app is not ready yet but you want the user to see something, so when the setting isLoading is true, show some loading bar and when it becomes false show the app... Use ng-if binded to the isLoading to render all the app content when ready and the spinner when not ready
Upvotes: 0
Reputation: 811
Are the contents of this json file going to be accessed from within your controllers? If so I would recommend creating an api for accessing it in a service that gets passed into every controller that needs it.
Next comes the question of (when do you NEED it). If it's something that can be loaded asynchronously then have the $http.get method within the initialization of the service. If it needs to be loaded up BEFORE the application or controllers load, then maybe consider loading it as part of the page and accessing it through the global scope.
<script src="config.json"></script>
The async method is the prefered method and you should REALLY try that before you start putting it into the global scope.
Update of what the service should look like
.service('ConfigService', function($http) {
var ConfigService = {};
ConfigService.config = {};
ConfigService.load = function() {
$http.get('/config').then(function(response){
this.config = response.data
});
};
ConfigService.load();
return ConfigService;
});
Then from in your controllers you would access ConfigService.config;
Upvotes: 0
Reputation: 3186
I can think of a few methods to handle this.
If you are using something like php to write your index page, you could write the contents of that file to the index page before the page is processed by the browser.
<?php
//load the contents of the config file
$configContents = file_get_contents('./config.json');
?>
<html>
<head>
<!--all your script and css includes here-->
<script>
var configJson = <?php echo $configContents; ?>
module.constant('config', configJson );
</script>
<!-- rest of your page... -->
Based on this post, it looks like you can use the injector to get services, and then you can manually bootstrap your application (based on this documentation) after loading the required data. (I haven't tested this...)
angular.injector(['ng']).get('$http').get('./config.json').then(function(response){
module.constant('config', response.data);
//manually bootstrap your application now that you have gotten your data
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
});
Upvotes: 3