AngularJS - Providers

The initial setup:

<div ng-app="app" ng-controller="AppCtrl">
  {{ title }}
</div>
var app = angular.module("app",[]);

app.factory("game", function () {
  return {
    title: "StarCraft"
  };
});

app.controller("AppCtrl", function ($scope, game) {
  $scope.title = game.title;
});

Factories are a common paradigm in Angular that allow you to configure a function that returns an object which can be then injected into controllers. Here, the game parameter to the controller is injected and matched to the game factory, which returns an object with a title attribute.

But what is a factory?

To demonstrate the factory can be refactored into the $provide service:

var app = angular.module("app",[]);

app.config(function ($provide) {
  $provide.factory("game", function () {
    return {
      title: "StarCraft"
    };
  });
});

app.controller("AppCtrl", function ($scope, game) {
  $scope.title = game.title;
});

The $provide service sets up the injector for any factories defined on it. The above example functions identically to the initial setup.

$provide.factory is shorthand for $provide.provider, which sets up a more generic provider which returns objects that have $get functions:

var app = angular.module("app",[]);

app.config(function ($provide) {
  $provide.provider("game", function () {
    return {
      $get: function () {
        return {
          title: "StarCraft"
        };
      }
    };
  });
});

app.controller("AppCtrl", function ($scope, game) {
  $scope.title = game.title;
});

This also functions identically to the initial setup. ‘factory’ is simply an alias for this longhand method of declaring a provider which returns an object with a $get method.

Refactor

In config, since we are declaring a provider on the $provide service, we can just as easily migrate the provider out of config and directly onto the app.provider method:

var app = angular.module("app",[]);

app.provider("game", function () {
  var type;
  return {
    setType: function (value) {
      type = value;
    },
    $get: function () {
      return {
        title: type + "Craft"
      };
    }
  };
});

app.config(function (gameProvider) {
  gameProvider.setType("War");
});

app.controller("AppCtrl", function ($scope, game) {
  $scope.title = game.title;
});

This allows us to inject the gameProvider and configure it further. Here, we define a setType method within the returned provider object, and invoke the method on the provider in the app.config method. This exposes an API to the provider, accessible in app.config, that allows further configuration of that provider to occur before it reaches the controller.