Search code examples
angularjsrootscopeangularjs-rootscope

Why I can't set/get $rootScope?


I try to set a a value in $rootScope in a .run() and try to get it in a service but it looks like it's undefined. Everything else in the .run() and in the service is running fine.

.run(function($ionicPlatform, $translate, $rootScope) {
  document.addEventListener("deviceready",function(){ onDeviceReady($rootScope); }, false);

  function onDeviceReady($rootScope) {
    if(typeof navigator.globalization !== "undefined") {
      navigator.globalization.getPreferredLanguage(function(language) {
        $rootScope.language='en'; //(language.value).split('-')[0];
        $translate.use((language.value).split("-")[0]).then(function(data) {
          console.log("SUCCESS -> " + data);
        }, function(error) {
          console.log("ERROR -> " + error);
        });
      }, null);
    }
  }
})


.service('Webcache', function ($http, $q, apiHost, $rootScope) {
    return {
        getDataBySection: function (section, version, params) {
            var params = params || {};
            var host = apiHost;
            var deferred = $q.defer();
            var start = new Date().getTime();

            params.lang = $rootScope.language;

            $http.get('http://'+ host +'/api/'+ version +'/'+ section, {
                cache: true,
                params: params
            }).success(function (response) {
                deferred.resolve(response);
            }).error(function (response){
                deferred.resolve(false);
            });
            return deferred.promise;
        }
    };
})

Solution

  • You shouldn't be binding to the onDeviceReady event at all. Ionic gives you an angular compatible way to handle it: $ionicPlatform.ready() which returns a promise. Using this would make your code look something like this:

    .run(function($ionicPlatform, $translate, $rootScope, $q, $log) {
       $rootScope.languagePromise = $ionicPlatform.ready()
       .then(function() {
            return $q(function(resolve, reject) {
                if(angular.isDefined(navigator.globalization)) {
                    navigator.globalization.getPreferredLanguage(function(language) {
                        $translate.use((language.value).split("-")[0]).then(function(data) {
                            $log.debug("SUCCESS -> " + data);
                            resolve(language);
                        }, function(error) {
                            $log.debug("ERROR -> " + error);
                            reject(error);
                        });
                    }, null);
                } else { resolve('en'); }
            });
        });
    
    })
    

    This puts a promise in the scope which you can use at any time to get the language either immediately (if the initialisation is completed), or when it becomes available.

    .service('Webcache', function ($http, apiHost, $rootScope) {
        return {
            getDataBySection: function (section, version, params) {
                params = params || {};
                var host = apiHost;
                return $rootScope.languagePromise.then(function(language) {
                    params.lang = language;
                    return $http.get('http://'+ host +'/api/'+ version +'/'+ section, {
                        cache: true,
                        params: params
                    }).catch(function (){
                        return false;
                    });
                });
            }
        };
    })
    

    The getDataBySection directly method returns the result of waiting on the language promise which in turn depends on the result of the $http promise, so the response data will propagate back just as for your existing code.