Skip to content
Thomas David Kehoe edited this page Jul 13, 2017 · 23 revisions

Services are typically said to be a good idea because they modularize your code. But there's a more important reason to use services. $scope shares data between controllers and templates. It doesn't share data between controllers. To share data between controllers you use a service. If you're having issues with child scopes and parent scopes, maybe you should be using a service.

Angular has five types of services:

  • Value and Constant returns a value. They always return the same value.
  • A factory receives a value, runs a function using the value, and returns a new value.
  • A service creates a new function (using the new keyword). This is useful for object-oriented programming (OOP).
  • Providers do the same things as the above services but with more verbose syntax, enabling more control, including using .config.

Provider Checklist

  1. Make a file for the service, starting with app.value();, app.factory(); etc.
  2. Name the service, e.g., app.value('message');.
  3. Save the file in the services directory. Name it with myValue.js, myFactory.js, etc.
  4. Link from index.html to the service, e.g.,
<script type="text/javascript" src="javascript/services/myValue.js"></script>
<script type="text/javascript" src="javascript/services/myFactory.js"></script>
  1. Inject the service as a dependency into the controller, either

You inject the value as a dependency thus, and then call it:

app.controller("myController", ["$scope", "myValue", function ($scope, myValue) {
...
}];

Listing the dependency twice is done in case you intend to minimize your code. If you don't intend to minimize your code, save time and complexity:

app.controller("myController", function ($scope, myValue) {
...
};
  1. Now you can write your service.

Value and Constant

The service is the second parameter. For a value it's just the value:

app.value("myValue", 9001);
app.value("myValue", "Hello world!");

myValue is the name of the value. 9001 or Hello world! is the value.

To call the value from the controller, use the name of the service:

$scope.powerValue = myValue;

The value can be an object:

app.value("myObject", {
   animal: cat,
   food: mice.
   sound: purr
}
);

Then you can call properties:

$scope.myAnimal = myObject.animal;

The difference between values and constants has to do with configurations and decorators.

Factory

Factories are like values except that the second parameter is a function. The factory syntax is:

app.factory('myFactory', function() {
...
});

You can inject dependencies:

app.factory('myFactory', function(dependency, anotherDependency) {
...
});

No $scope in factories

But you can't inject $scope into services. The purpose of a service is to pass data between controllers, and each controller has its own $scope. Services have to be outside of all the scopes. Instead you use return to pass data out of a service.

You can pass data into a factory through dependencies.

Use a factory to pass data between controllers

app.factory('sharingFactory', function() {

// receive data from a controller
let fromController = function(data) {
   myData = data;
}

// send data to a controller
let toController = function() {
   return myData;
}

return {
   fromController = fromController,
   toController = toController
};

});

In the first controller, we send the data with:

sharingFactory.data = 9001;

Call your factory

Angular factories use "lazy instantiation." That means that a factory executes when it's injected as a dependency, not when it's called. What's lazy about this I don't know, maybe the Angular developers were too lazy to make factories execute when you want them to. To make a factory execute when it's called you must create an object called return within the factory:

app.factory("myFactory", function() {
  console.log("Factory injected!");

  return {
    executeMyFactory: function() {
      console.log("Factory executed!");
    }
  }

});

In the controller you then call the object:

console.log("This is just before the factory is called.")
authorizedUserFactory.queryGetRecord(); // call factory
console.log("This is just after the factory is called.")

You should then see:

This is just before the factory is called.
Factory called!
This is just after the factory is called.

Service

A service can pass data between controllers.

Provider

Constant

Clone this wiki locally