Passing current scope to an AngularJS Service

AngularjsData BindingAngularjs ScopeAngular Services

Angularjs Problem Overview


Is it correct to pass the "current" $scope to an AngularJS service?

I'm in the situation where I've a $service knowing it's consumed by only one controller, and I'd like to have a reference to the controller's scope in the $service methods themselves.

Is this philosophically correct?

Or I'd better to broadcast events to the $rootScope and then make my controller listen to them?

Angularjs Solutions


Solution 1 - Angularjs

To let the controller know when something async happens, use Angular promises.

To provoke the $apply, you don't need the scope, you can call $rootScope.$apply, as there is no difference calling it in a specific scope or in the root.

Regarding the variable reading, it would be better if you received parameters. But you could also read it from a scope as an object parameter, but I would go with parameter, that would make your service interface much more clearer.

Solution 2 - Angularjs

I would say if your functionality is specific to one controller only than you don't need a service.

The controllers tasks is to manipulate the specific model whereas a service should deal with global tasks. I would rather stick to this paradigm instead of mixing things up.

This is what the docs say

Service

> Angular services are singletons that carry out specific tasks common to web apps

Controller

> In Angular, a controller is a JavaScript function(type/class) that is used to augment instances of angular Scope, excluding the root scope.

PS: Apart from that if you need to digest you can also inject the $rootScope within your service.

Solution 3 - Angularjs

Yes. You can pass the $scope into the service when you initialize it. In the service constructor you can assign the scope to something like this._scope and then reference the scope within the service!

angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {

	$scope.someVar = 4;

	$scope.blahService = new blahService($scope);

});

angular.module('blah').factory('blahService', function() {

	//constructor
	function blahService(scope) {
		this._scope = scope;

		this._someFunction()
	}

	//wherever you'd reference the scope
	blahService.prototype._someFunction = function() {

		this._scope['someVar'] = 5;

	}

	return blahService;

});

Solution 4 - Angularjs

I personally believe that passing the whole $scope to a service is a bad idea, because it creates a kinda circular reference: the controller depends on the service and the service depends on the scope of the controller.

On top of being confusing in terms of relations, things like this one end up getting in the way of the garbage collector.

My preferred approach is to put a domain object in the controller scope and pass that to the service. This way the service works regardless whether it's used inside a controller or maybe inside another service in the future.

For example, if the service is supposed to push and pop elements from an array errors, my code will be:

var errors = [];
$scope.errors = errors;
$scope.myService = new MyService(errors);

The service interacts then with the controller by operating on errors. Of course I've got to be cautious about never wiping out the whole array reference, but at the end of the day that's a general JS concern.

I'd never want to use broadcasting, $apply and/or similar things, because imho good OO-practices will always trump whatever Angular-magics.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionS.C.View Question on Stackoverflow
Solution 1 - AngularjsCaio CunhaView Answer on Stackoverflow
Solution 2 - AngularjsF LekschasView Answer on Stackoverflow
Solution 3 - Angularjsuser12121234View Answer on Stackoverflow
Solution 4 - AngularjsMarco FaustinelliView Answer on Stackoverflow