Angular: Providers and derivatives

by net_uk_sweet

HTML

<div ng-controller="mainCtrl as main">
    <h1>{{main.title}}*</h1>
    <h2>{{main.strapline}}</h2>
    <p>Earn {{main.earn}} per click</p>
    <p>You've earned {{main.earned}} by clicking!</p>
    <button ng-click="main.handleClick()">Click me to earn</button>
    <small>* Not actual money</small>
</div>

CSS

div { border: 1px solid black; padding: 0 10px 10px 10px }
button { display: block; }

JavaScript

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

// A CONSTANT is not going to change
app.constant('range', 100);

// A VALUE could change, but probably / typically doesn't
// I had no success at all observing changes to a non-primitive VALUE
// between controllers(?)
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');

// A simple FACTORY allows us to compute a value.
// It's calculated once, and that is the value which is injected everywhere.
// Essentially a VALUE but one with which we can compute a result @ runtime.
// A FACTORY can return objects and functions, as well as primitive types. 
// We can return something which looks very similar to the module pattern in 
// which an API is defined in the returned object (but we won't here)
app.factory('random', function randomFactory(range) {
    // Get a random number within the range defined in our CONSTANT
    return Math.random() * range;
});

// A SERVICE is effectively the same, though it takes a constructor
// function as the argument and invokes it using the new keyword.
// This bloke doesn't use them, which is good enough for me:
// http://demisx.github.io/angularjs/2014/09/14/angular-what-goes-where.html
// Though clearly the ability to inherit could prove powerful in some instances

// A PROVIDER, however, needs to return a custom type which implements the 
// functionality provided (see what I did there?) by our service.
// So here I define the constructor for the custom type my provider will 
// instantiate and return.
var Money = function(locale) {
        
    // Depending on locale string set during config phase, we'll
    // use different symbols and positioning for any values we 
    // need to display as currency
    this.settings = {
        uk: {
            front: true,
            currency: '£',
            thousand: ',',
            decimal: '.'
        },
        eu: {
            front: false,
            currency: '€',
            thousand: '.',
  ...