Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusable AngularJS Service within an App

I'm very new to AngularJS, so it's possible I'm asking the entirely wrong question. What I'm trying to accomplish is create a reusable class with data binding in a single app. The following demonstrates what I'm trying to accomplish with a very simple example.

Say I want to create a counter with a value and an increment method. I can create a service and use it in a controller like so:

angular.module("fiddle", ["counter"])
.controller("MainCtrl", function($scope, counter) {
    $scope.counter = counter;
});

angular.module("counter", [])
.service("counter", function() {
    this.count = 0;
    this.increment = function(x) {
        this.count += x;
    };
});

Then I can display a view to add a counter:

<h1>Count: {{counter.count}}</h1>
<button ng-click="counter.increment(1)">Add 1</button>
<button ng-click="counter.increment(5)">Add 5</button>
<button ng-click="counter.increment(10)">Add 10</button>

This works fine for one counter, but what if I want to have multiple counters in the same controller? Since the service is a singleton, I can't do that. What's the best approach for creating something like this with Angular given that other services would be much more complex? Thanks!

http://jsfiddle.net/jeffaudio/ExASb/

like image 568
jeffaudio Avatar asked Aug 05 '13 15:08

jeffaudio


2 Answers

To make a service not act like as a singleton you can do this:

angular.module("counter", [])
.service("counter", function() {
    var aCounter = function() {
        this.count = 0;
        this.increment = function(x) {
            this.count += x;
        };
    }
    return {
        getInstance: function () {
          return new aCounter();
        }
    };
});

And then manage your counters from your controller, e.g:

function myCtrl($scope, counter) {
    $scope.counter1 = counter.getInstance();
    $scope.counter2 = counter.getInstance();
}

http://jsfiddle.net/KLDEZ/

like image 92
StuR Avatar answered Sep 22 '22 00:09

StuR


Make your service support multiple counters:

angular.module("counter", [])
.service("counter", function() {
    // Counters is our object which service encapsulates
    this.counters = {};
    this.increment = function(name, x) {
        // If such counter is not set, set it.
        if (!this.counters[name]) { this.counters[name] = 0; }
        this.counters[name] += x;
    };
});

And then:

<button ng-click="counter.increment('count1', 1)">Add 1</button>
<button ng-click="counter.increment('count2', 5)">Add 5</button>
<button ng-click="counter.increment('count3', 10)">Add 10</button>

And bind the view to whatever counter you want...

like image 21
Shay Friedman Avatar answered Sep 20 '22 00:09

Shay Friedman