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: '.',
...