5

Let's suppose I create a factory, service, or provider object like so

myApp.factory('myService', function() {
  return {
    counter: 0,
    increment: function() {
      console.log('counter: ' + (this.counter++))
    }
  };
});

And suppose I have a controller that depends on it

myApp.controller('myCtrl', function(myService) {
  $scope.incr = function() {
    myService.increment();
  };
}

And I apply this controller in different parts of the html

<div ng-controller="myCtrl">
  <button ng-click="increment()">increment</button>
</div>
...
<div ng-controller="myCtrl">
  <button ng-click="increment()">increment</button>
</div>

Right now, when I click on each button, the counter is universal and it goes 0, 1, 2, 3, ...

How can I write my factory, service, or provider so that each controller gets a different copy of the service object?

kane
  • 5,465
  • 6
  • 44
  • 72
  • 1
    All services in angular are singletons. What you want is a factory service, which you can use to create your service. E.g. `MyServiceFactory`, inject this into the controller and let it have a method to create a `myService`. – Yoshi Jun 19 '15 at 23:52
  • Hi @Yoshi. Yes, I've read that all services are singletons which is why I'm having trouble creating separate instances. Can you elaborate on what you mean by creating a factory service and injecting it into the controller? Isn't that what I have done in my example? – kane Jun 19 '15 at 23:54
  • 1
    Not really. You used a concrete service (instantiated by angular), which then is shared through injection. You need another service (the above mentioned factory, or similar), with which you would provide your own creation method for a `myService` to be used inside the controller. E.g. `var myService = MyServiceFactory.createService();` – Yoshi Jun 19 '15 at 23:56
  • I think you're suggesting to do this outside of angular. if you wouldn't mind posting a full solution as an answer, I can accept the answer in a few days after people have had a chance to chime in with their methods as well. Thanks – kane Jun 20 '15 at 00:03

2 Answers2

5

Since factories are singletons you will need to use a method in your factory to create your service each time. Change your service to have a create method that returns your service that does the incrementing:

myApp.factory('myService', function() {
  return {
    create: function () {
      return { 
        counter: 0,
        increment: function() {
          console.log('counter: ' + (this.counter++));
        }
      };
    }
  };
});

myApp.controller('myCtrl', function($scope, myService) {
  var service = myService.create();
  $scope.incr = function() {
    service.increment();
  };
});

Also the controller method name doesn't match up to what is in the view:

<div ng-controller="myCtrl">
  <button ng-click="incr()">increment</button>
</div>
...
<div ng-controller="myCtrl">
  <button ng-click="incr()">increment</button>
</div>

Plunkr

Wayne Ellery
  • 7,888
  • 1
  • 28
  • 45
0

Simply change .factory to .service, this will provide a unique scope each time you inject it.

The reasons for this are better described in this answer: AngularJS: Service vs provider vs factory

Community
  • 1
  • 1
myrcutio
  • 1,045
  • 9
  • 13