3

I am using $rootScope.$emit() for raising events from service to controller.

It is working fine when emitting from the instance of service that is referenced in controller but $rootScope.$on is not getting called when emitting from the instance of service I got from angular injector in plain javascript .

Following is my code

Plain JavaScript

    var msgHandlerJS = function () {
    var injector = angular.injector(['ng', 'services']);
    var aMsgHandlerService = injector.get('msgHandlerService');

    aMsgHandlerService.TestScopeWatch();
}

Calling the above when dom is ready :

angular.element(document).ready(function () {    
    msgHandlerJS();
});

Service

(function (module) {    

    var msgHandlerService = function ($rootScope, $http, $q, $timeout) {  
        var TestScopeWatch = function () {
            $http.get('~/test.json').then(function (result) {
                EmailPacket = result.data.Packet;

                $rootScope.$emit("EmailPacketChanged", EmailPacket);     
            });
        };

        return {
            //making public
            TestScopeWatch:TestScopeWatch,
        };
    };

    module.factory("msgHandlerService", ["$rootScope","$http", "$q","$timeout", msgHandlerService]);

}(angular.module("services")));

Controller

(function (module) {   
    function testController($rootScope,$scope, msgHandlerService) {
        $rootScope.$on("EmailPacketChanged", function(event,data){
            alert('Here I am');
        };
    };

    module.controller("testController", ["$rootScope","$scope", "msgHandlerService",  testController]);    

}(angular.module('app')));
6
  • @pherris It is working fine when emitting from the instance of service that is referenced in controller but $rootScope.$on is not getting called when emitting from the instance of service I got from angular injector in plain javascript . Commented Jun 3, 2015 at 18:44
  • @kumaro, can you provide your hrml? Commented Jun 3, 2015 at 18:45
  • Did you confirm that you are executing $rootScope.$emit? Commented Jun 3, 2015 at 18:47
  • 1
    Do you have an ng-app on the page? Commented Jun 3, 2015 at 18:47
  • @pherris Yes, emit is executing . I see a network call to get test.json Commented Jun 3, 2015 at 18:51

1 Answer 1

7

You need to get the proper injector of the application, angular.injector creates a new injector, it has nothing to do with the injector that bootstrapped your app. So the instance of the service (yourService, rootScope inside it) you get from that injector is different instance than what is in the app. You should instead use the getter .injector() from the rootElement of the application.

i.e if you have an ng-app or manually bootstrapping, get the injector out of that element. Example:

 var injector = angular.element(document.querySelector('[ng-app]')).injector();

If your app root is document (html) then get injector from the document i.e :

var injector = angular.element(document).injector()

Also if you want any scope bindings to reflect you also need to invoke a digest cycle (alert will work fine ofcourse):

var msgHandlerJS = function() {
   var injector = angular.element(document).injector();
   var aMsgHandlerService = injector.get('msgHandlerService');
   var $rootScope = injector.get('$rootScope');
   aMsgHandlerService.TestScopeWatch();
   $rootScope.$digest();
}

(function(module) {

  var msgHandlerService = function($rootScope, $http, $q, $timeout) {
    var TestScopeWatch = function() {
      //$http.get('~/test.json').then(function(result) {
      //  EmailPacket = result.data.Packet;

      $rootScope.$emit("EmailPacketChanged", {});
      // });
    };

    return {
      //making public
      TestScopeWatch: TestScopeWatch,
    };
  };

  module.factory("msgHandlerService", ["$rootScope", "$http", "$q", "$timeout", msgHandlerService]);

}(angular.module("services", [])));

(function(module) {
  function testController($rootScope, $scope, msgHandlerService) {
    $rootScope.$on("EmailPacketChanged", function(event, data) {
      $scope.got = "got the message!!";
    });
  }

  module.controller("testController", ["$rootScope", "$scope", "msgHandlerService", testController]);

}(angular.module('app', ['services'])));

var msgHandlerJS = function() {

  var injector = angular.element(document.querySelector('[ng-app]')).injector();
  var aMsgHandlerService = injector.get('msgHandlerService');
  var $rootScope = injector.get('$rootScope');
  aMsgHandlerService.TestScopeWatch();
  $rootScope.$digest();
}
angular.element(document).ready(function() {
  msgHandlerJS();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="test" ng-app="app" ng-controller="testController">
  {{got}}
</div>

Sign up to request clarification or add additional context in comments.

8 Comments

@PSL Thanks bro! It's the injector. I think I am creating a new one instead of using the existing one. following line fixed it angular.element(document.querySelector('[ng-app]')).injector();
@kumaro yes you are.. That injector has nothing to with the one bootstrapped your application... So it is like you are invoking method on a different instance of the service.
Thanks for clearing that. Now that I know it makes more sense. Is it the fastest way to get injector ? Not sure if query selector goes through each & every element looking for 'ng-app' and slow down the application
@kumaro where is your ng-app? on the html? Also see my answer update with links to official documentations.
@PSL It's on a div further down
|

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.