2

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.

3
  • 1
    Put your rootService in a factory/service/provider not in config. BTW I wouldn't use $rootScope but $window and all in all I'd use constant/value for the app config rely on a promise for the config it's not the way to go imo Commented Feb 22, 2014 at 19:54
  • Thanks for reply! Can you publish your code? Commented Feb 22, 2014 at 20:39
  • Are you trying to set global variable from some API response or it is static ? Commented Jun 23, 2016 at 6:22

4 Answers 4

1

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();       
});
Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

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);


}])

Comments

0

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

1 Comment

I'm looking for a way to do this too. What's the $q for in the app.js?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.