ProfK
ProfK

Reputation: 51064

Why can't I inject my service?

I have the following new service:

var SignatureService = function ($scope) {

    this.announce = function () {
        alert($scope.specificName);
    }
};
SignatureService.$inject = ['$scope'];

This is declared for the app as follows:

MyAngularApp.service('SignatureService', SignatureService);

Several other services are added to the app in exactly the same way, and they all seem to work OK. I then have a controller declared and defined as follows:

MyAngularApp.controller('MyController', MyController);
...
var MyController = function ($scope, Service1, Service2, $location, $modal, SignatureService) {
...
}
MyController.$inject = ['$scope', 'Service1', 'Service2', '$location', '$modal', 'SignatureService'];

I am simply using the slightly unconvcentionaly manner of defining the servivce and injecting it that is standard in the app I am working on, as this works for all existing services, and I would prefer to simply slot mine in as per standard.

When the controller loads, I get an [$injector:unpr] in the browser console, with the error info:

$injector/unpr?p0=$scopeProvider <- $scope <- SignatureService

Upvotes: 2

Views: 93

Answers (1)

dfsq
dfsq

Reputation: 193261

You can't inject $scope into your custom service. It just doesn't make sense since SignatureService can be injected anywhere including other services and other controlles. What $scope is supposed to be if you say inject it into two nested controllers, which one should be injected?

Scope object ($scope) is always associated with some DOM node, it is attached to it. That's why you see $scope in controllers and directives. And this is the reason why you can't have it in service: services are not related to specific DOM elements. Of course you can inject $rootScope but this is unlikely what you need in your question.

Summary: $scope is created from the $rootScope and injected in necessary controllers, but you can't injected it into custom service.

UPD. Based on comments you want to use service to define reusable controller methods. In this case I would go with what I call mixin approach. Define methods in the service and mix them in the necessary controllers.

app.service('controllerMixin', function() {
    this.getName = function() {
        alert(this.name);
    };
});

and then extend controller scope with angular.extend:

app.controller('OneController', function($scope, controllerMixin) {
    angular.extend($scope, controllerMixin);
    // define controller specific methods
});

app.controller('TwoController', function($scope, controllerMixin) {
    angular.extend($scope, controllerMixin);
    // define controller specific methods
});

This is pretty effective, because controllerMixin doesn't have any notion of $scope whatsoever, when mixed into controller you refer to the scope with this. Also service doesn't change if you prefer to use controllerAs syntax, you would just extend this:

angular.extend(this, controllerMixin);

Demo: http://plnkr.co/edit/ePhSF8UttR4IgeUjLRSt?p=info

Upvotes: 4

Related Questions