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?
- 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
1 Answer
Reset to default 6You 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){});