最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why do events from provider not $emit to $rootScope? - Stack Overflow

programmeradmin0浏览0评论

To keep things de-coupled in my AngularJS app, I've got a single validationService that different controllers may call to perform the validation. As it is, the validate() method in a given controller should just $emit an event (request:validate, for example) which the service will listen for -- but it does not appear that $rootScope ever receives the emitted event. For example:

angular.module('mine').controller('CommitController', [
    '$scope',
    function($scope) {
        $scope.validate = function() {
            $scope.$emit('request:validate');
        };
    }
]);
angular.module('mine.services').factory('validationService', [
    '$rootScope',
    function($rootScope) {
        $rootScope.$on('request:validate', function(e) {
            console.log('received the request:validate event - go ahead with validation');
        });
    }
]);

But the $on('request:validate') never fires from $rootScope. Does $rootScope not receive events emitted from child scopes? Is there some quirk in how $rootScope listens to events?

Is there a "more Angular" approach to this? Should the controllers simply call validationService directly? Should the events $broadcast from $rootScope to begin with?

To keep things de-coupled in my AngularJS app, I've got a single validationService that different controllers may call to perform the validation. As it is, the validate() method in a given controller should just $emit an event (request:validate, for example) which the service will listen for -- but it does not appear that $rootScope ever receives the emitted event. For example:

angular.module('mine').controller('CommitController', [
    '$scope',
    function($scope) {
        $scope.validate = function() {
            $scope.$emit('request:validate');
        };
    }
]);
angular.module('mine.services').factory('validationService', [
    '$rootScope',
    function($rootScope) {
        $rootScope.$on('request:validate', function(e) {
            console.log('received the request:validate event - go ahead with validation');
        });
    }
]);

But the $on('request:validate') never fires from $rootScope. Does $rootScope not receive events emitted from child scopes? Is there some quirk in how $rootScope listens to events?

Is there a "more Angular" approach to this? Should the controllers simply call validationService directly? Should the events $broadcast from $rootScope to begin with?

Share Improve this question edited Nov 11, 2015 at 17:59 CLo 3,7304 gold badges28 silver badges45 bronze badges asked Aug 1, 2013 at 15:19 founddramafounddrama 2,4111 gold badge23 silver badges31 bronze badges 5
  • Why not just use the validation service directly? why do you have to listen? – Fresheyeball Commented Aug 1, 2013 at 18:04
  • @Fresheyeball - That is an excellent question and is certainly another approach I could take. Calling methods on the service directly may prove to be more appropriate, but I was also puzzled by why the events didn't appear to be making it to the $rootScope. – founddrama Commented Aug 1, 2013 at 18:09
  • I understand and your question is valid and useful, it just that in this case it seems indicative of a structural design flaw. For services, direct usage of a method seems to be the preferred methodology. $emit is more prevalent used inside directives, with the listeners taking place in controllers. Just an FYI. – Fresheyeball Commented Aug 1, 2013 at 18:12
  • @Fresheyeball - that makes sense -- but given what you're describing, why not call the services directly from the directives? Unless I'm misinterpreting and what you mean is that you don't want to call service code in the first place and thus $emit is used to "call" methods in the controller from the directives. – founddrama Commented Aug 1, 2013 at 19:11
  • I would call the service directly from the directive. IMHO the purpose of $emit and $on is for directive -> controller, and global messaging. Services should always get called directly. – Fresheyeball Commented Aug 1, 2013 at 20:16
Add a ment  | 

1 Answer 1

Reset to default 6

You are not instantiating validationService therefore the listener does not get attached. Include it in the module and inject it to the controller.

angular.module('mine',["mine.services"]).controller('CommitController', [
    '$scope', "validationService",
    function($scope, vs) {
        $scope.validate = function() {
            $scope.$emit('request:validate');
        };
    }
]);
angular.module('mine.services',[]).factory('validationService', [
    '$rootScope',
    function($rootScope) {
        $rootScope.$on('request:validate', function(e) {
            console.log('received the request:validate event -'+
                         'go ahead with validation');
        });
    }
]);

If you don't want to inject the service into controller, you do the binding in module's run method

angular.module("mine", ["mine.services"]).run(function(validationService){});
发布评论

评论列表(0)

  1. 暂无评论