0

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.

3 Answers 3

1

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

3 Comments

Wauww I was soo close. And this makes much more sense. Thank you!
@JeroenE this should work using $scope.$watch and be safer. The watch from $rootScope will probably not be cleaned if this is put in a controller and the current route/state change. Leaving one/more watch each time you pass in this code slowing the application.
@JeroenE can use $scope.$watch('$root.events', ...) to solve that problem.
0

RootScope documentation

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

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

3 Comments

Thank you, this works great but what does the "return $rootScope.events"?
It is the value function parameter. See this tutorial. It's basically an overload that expects a function which returns the value instead of a string which names the value.
Also, see the $watch documentation here.
0

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

Comments

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.