JeroenE
JeroenE

Reputation: 703

AngularJS get rootScope variable when set

In a project I'm working on we've got a variable on the $rootScope called events. I can access this in my controllers using $rootScope.events after injecting it to my controller.

It can take some time before the service sets the events on the $rootScope variable. Now am I adding a new functionality that needs the ID from the first event of the variable. The problem is, it's getting called before $rootScope.events is set. I can't figure out how to call the method in my controller after the $rootscope.events is set. I have used $watch before, how ever, it doesn't seem to work on this variable. The code I tried:

$scope.$watch('$rootScope.events', function() {
    if ($rootScope.events.length > 0) {
        getDetails(); // function I want to call after $rootscope.events is set
        $log.debug($rootScope.events); // debugging line
    }
});

I added the $rootScope.events.length > 0 to avoid it's getting in a infinite loop. Not sure if this is necessary. Is there a solution for what I need to add this functionality? Something like this watch? Or have I done something wrong?

I don't think you need more code then I've added to this post as I just inject $scope and $rootScope in my controller, and then $log.debug() should get called with the set variable. Currently it returns an empty variable. If I'm wrong just let me know in the comments.

Upvotes: 0

Views: 1946

Answers (3)

bugged87
bugged87

Reputation: 3142

It's been awhile, but I think you want this:

$rootScope.$watch('events', function() {
    if ($rootScope.events.length > 0) {
        getDetails(); // function I want to call after $rootscope.events is set
        $log.debug($rootScope.events); // debugging line
    }
});

events is a value on $rootscope but $rootscope.events is not a value on $scope.

To avoid cluttering $rootscope with watches, however, you should probably use:

$scope.$watch('$root.events', function() {
    var events = $scope.$root.events;
    if (events.length > 0) {
        getDetails(); // function I want to call after events is set
        $log.debug(events); // debugging line
    }
});

Or simply:

$scope.$watch('$root.events', function(newValue, oldValue) {
    if (newValue.length > 0) {
        getDetails(); // function I want to call after events is set
        $log.debug(newValue); // debugging line
    }
});

Upvotes: 1

Walfrat
Walfrat

Reputation: 5353

Instead of putting a watch for something that happen once, you can use a promise which your events service will resolve when the events will be ready.

Event Service : ($rootScope & $q injected)
   // in constructor : 
     this.deferred = $q.defer();
     $rootScope.eventPromise = deferred.promise;


    // in a setup fonction or even within the constructor
    setupEvent : function(){
       .. doing some stuff ..
        .. somewhere in a asynchronous call back : 
            $rootScope.events =... //setup events
            this.deferred.resolve();// or me.deferred using var me=this if some closure trouble

       .. somewhere else if it fails ..
            this.deferred.reject();
    }

Now let's be sure this will run before any controller will be loaded :

angular.run(['EventService', function(EventService){
    // if you do everything in the constructor let the angular.run and don't run any code, 
    // this will make sure your events will start loading before angular will resolve the current routes.
    EventService.setupEvent();
}]); 

Now let's use it :

$rootScope.eventPromise.then(function(){
    $rootScope.events // we're safe here.
});

Upvotes: 0

Norbert Huurnink
Norbert Huurnink

Reputation: 1316

RootScope documentation

Watch is on a string (scope variable) or a function.

$scope.$watch(function() {
   return $rootScope.events;
}, function() {
   console.log($rootScope.events);
}, true);

Upvotes: 0

Related Questions