Reputation: 1732
I need to set global config variable for my App populated with $http.get(url);
.run(['$http', '$rootScope','rootService', function($http, $rootScope, rootService) {
rootService.getApplicationConfig().success(
function(data, status) {
$rootScope.appSettings = data;
}
);
I can use it in html with {{appSettings.SomeValue}}. The problem that .run method executes after .config. And in controllers appSettings is undefined.
How can I get this working in controllers? Or make global variables, which would be populated only once startup.
Upvotes: 2
Views: 11825
Reputation: 285
Note: Don't use .run(). The method is runs async and you won't always have your data!
Use the value provider with an AppController.
Example:
Declaring a value (do this in your app.js):
angular.module('app', ['ui.router'])
.value('appSettings', { myValue: undefined })
appSettings is now an injectable service. Use like this:
angular.module('ctrls.myCtrl', [])
.controller('myCtrl', ['appSettings', function(appSettings) {
console.log(appSettings.myValue);
}]);
Setting the value from a server resource when the application starts.
Declare the AppController (i usually do this in my app.js):
.controller('appCtrl', ['rootService', 'appSettings', function (rootService, appSettings) {
var vm = this;
vm.loaded = false;
if (appSettings.myValue == undefined) {
rootService.getApplicationConfig().success(
function(data, status) {
appSettings.myValue = data;
vm.loaded = true;
}
);
}}]);
In the body of your main html page (the boot css class shows some sort of loading screen):
<div ng-controller="appCtrl as vm">
<div class="boot" ng-show="!vm.loaded"></div>
<div ng-if="vm.loaded" ui-view="main" role="main" class="main"></div>
</div>
The rest of the controllers in your application are loaded in the ui-view="main", only after the appCtrl has loaded your server settings. This way you always have your appSettings.
Upvotes: 1
Reputation: 32726
DONT USE THIS CODE
It's very tricky and I never put this code in my app ^^ The only way I found is:
'use strict';
angular.module('app', [])
.config(function () {
})
.run(function($rootScope,$timeout,Myconfig){
$rootScope.config = {};
Myconfig.get().then(function(data){
$rootScope.config = data;
});
})
.factory('Myconfig', function ($http,$q) {
return {
get : function() {
var deferred = $q.defer();
$http.get('config.json')
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
}
})
.controller('MainCtrl',function($scope){
$scope.$watch('config',function(){
console.log($scope.config);
});
});
If you get an eye on the console you can realize you can't use this code in prod at least I don't find any any to use a promise to retrieve a config from the server.
UPDATE I suppose it's your server so write server side a config js like
var config = {prop:1};
include in your page and than simply do
app.constant('CONFIG',config)
UPDATE
pseudo code
The only sensible thing I think of:
$routeProvider.when('/', {
controller: 'MyCtrl',
resolve: {
config: function(rootService) {
return rootService.getApplicationConfig()
}
}
})
app.controller('MyCtrl', function ($scope,MyService,config) {
MyService.set(config);
});
app.controller('MyCtrl', function ($scope,MyService) {
MyService.get();
});
Upvotes: 1
Reputation: 1732
Finally found an answer how to maker JSON only once!
in your app.js, where app = angular.module add
$provide.factory('appConfig', function ($q,rootService) {
return rootService.getApplicationConfig();
});
rootService.js
angular.module('projectApp').service('rootService', ['$http','$routeParams','API_URL',function ($http, $routeParams, API_URL) {
return {
getApplicationConfig: function() {
var url = API_URL+'/config/settings.json';
console.log(url);
return $http.get(url);
},
};
}]);
finally in your controller do like this
angular.module('projectApp').controller('MainCtrl', ['$location','$scope','$routeParams','rootService','appConfig', function ($location, $scope, $routeParams, rootService, appConfig) {
$scope.content = false;
appConfig.success(
function(data, status) {
console.log(data.time);
$scope.content = JSON.parse(data.config_homepage).content
}
);
}]);
On server side I push time to my JSON. Each time I use "appConfig" it show the same time. Which means that request goes to the server only once.
If someone have better solution, please post it as answer
Upvotes: 0
Reputation: 1732
Found solution with "value"
.value('appConfig',{
apiUrl: '/api',
settings: null
})
.run(['$http', '$rootScope','rootService','appConfig', function($http, $rootScope, rootService,appConfig) {
console.log(appConfig);
appConfig.settings = 'we can change it';
console.log(appConfig);
}])
Upvotes: 0