diff --git a/src/auto/injector.js b/src/auto/injector.js index b93446c0..8f8b78cf 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -253,83 +253,37 @@ function annotate(fn) { * * @description * - * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance. - * The providers share the same name as the instance they create with `Provider` suffixed to them. + * The {@link AUTO.$provide $provide} service has a number of methods for registering components with + * the {@link AUTO.$injector $injector}. Many of these functions are also exposed on {@link angular.Module}. * - * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of - * a service. The Provider can have additional methods which would allow for configuration of the provider. + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a property + * called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link AUTO.$provide $provide} service has additional helper methods to register + * services without specifying a provider. * - *
- *   function TrackingProvider() {
- *     this.$get = function($http) {
- *       var observed = {};
- *       return {
- *         event: function(event) {
- *           var current = observed[event];
- *           return observed[event] = current ? current + 1 : 1;
- *         },
- *         save: function() {
- *           $http.post("/track",observed);
- *         }
- *       };
- *     };
- *   }
- *
- *   describe('Tracking', function() {
- *     var mocked;
- *     beforeEach(module(function($provide) {
- *       $provide.provider('tracking', TrackingProvider);
- *       mocked = {post: jasmine.createSpy('postSpy')};
- *       $provide.value('$http',mocked);
- *     }));
- *     it('allows events to be tracked', inject(function(tracking) {
- *       expect(tracking.event('login')).toEqual(1);
- *       expect(tracking.event('login')).toEqual(2);
- *     }));
- *
- *     it('posts to save', inject(function(tracking) {
- *       tracking.save();
- *       expect(mocked.post.callCount).toEqual(1);
- *     }));
- *   });
- * 
- * - * There are also shorthand methods to define services that don't need to be configured beyond their `$get()` method. - * - * `service()` registers a constructor function which will be invoked with `new` to create the instance. You can specify services that will be provided by the injector. - * - *
- *    function TrackingProvider($http) {
- *      var observed = {};
- *      this.event = function(event) {
- *        var current = observed[event];
- *        return observed[event] = current ? current + 1 : 1;
- *      };
- *      this.save = function() {
- *        $http.post("/track",observed);
- *      };
- *    }
- *    $provider.service('tracking',TrackingProvider);
- *  
- * - * `factory()` registers a function whose return value is the instance. Again, you can specify services that will be provided by the injector. - * - *
- *    function TrackingProvider($http) {
- *      var observed = {};
- *      return {
- *        event: function(event) {
- *          var current = observed[event];
- *          return observed[event] = current ? current + 1 : 1;
- *        },
- *        save: function() {
- *          $http.post("/track",observed);
- *        }
- *      };
- *    }
- *    $provider.factory('tracking',TrackingProvider);
- *  
+ * * {@link AUTO.$provide#provider provider(provider)} - registers a **service provider** with the + * {@link AUTO.$injector $injector} + * * {@link AUTO.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link AUTO.$provide#value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link AUTO.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, that + * will be wrapped in a **service provider** object, whose `$get` property will contain the given + * factory function. + * * {@link AUTO.$provide#service service(class)} - registers a **constructor function**, `class` that + * will be wrapped in a **service provider** object, whose `$get` property will instantiate a new + * object using the given constructor function. * + * See the individual methods for more information and examples. */ /** @@ -338,7 +292,18 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * Register a provider for a service. The providers can be retrieved and can have additional configuration methods. + * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions are + * constructor functions, whose instances are responsible for "providing" a factory for a service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider and + * its service. Importantly, you can configure what kind of service is created by the `$get` method, + * or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a method + * {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. * * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key. * @param {(Object|function())} provider If the provider is: @@ -349,6 +314,70 @@ function annotate(fn) { * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`. * * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link AUTO.$provide#provider $provide.provider()}. + * + *
+ *  // Define the eventTracker provider
+ *  function EventTrackerProvider() {
+ *    var trackingUrl = '/track';
+ *
+ *    // A provider method for configuring where the tracked events should been saved
+ *    this.setTrackingUrl = function(url) {
+ *      trackingUrl = url;
+ *    };
+ *
+ *    // The service factory function
+ *    this.$get = ['$http', function($http) {
+ *      var trackedEvents = {};
+ *      return {
+ *        // Call this to track an event
+ *        event: function(event) {
+ *          var count = trackedEvents[event] || 0;
+ *          count += 1;
+ *          trackedEvents[event] = count;
+ *          return count;
+ *        },
+ *        // Call this to save the tracked events to the trackingUrl
+ *        save: function() {
+ *          $http.post(trackingUrl, trackedEvents);
+ *        }
+ *      };
+ *    }];
+ *  }
+ *
+ *  describe('eventTracker', function() {
+ *    var postSpy;
+ *
+ *    beforeEach(module(function($provide) {
+ *      // Register the eventTracker provider
+ *      $provide.provider('eventTracker', EventTrackerProvider);
+ *    }));
+ *
+ *    beforeEach(module(function(eventTrackerProvider) {
+ *      // Configure eventTracker provider
+ *      eventTrackerProvider.setTrackingUrl('/custom-track');
+ *    }));
+ *
+ *    it('tracks events', inject(function(eventTracker) {
+ *      expect(eventTracker.event('login')).toEqual(1);
+ *      expect(eventTracker.event('login')).toEqual(2);
+ *    }));
+ *
+ *    it('saves to the tracking url', inject(function(eventTracker, $http) {
+ *      postSpy = spyOn($http, 'post');
+ *      eventTracker.event('login');
+ *      eventTracker.save();
+ *      expect(postSpy).toHaveBeenCalled();
+ *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ *    }));
+ *  });
+ * 
*/ /** @@ -357,12 +386,32 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A service whose instance is the return value of `$getFn`. Short hand for configuring services if only `$get` method is required. + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link AUTO.$provide#factory $provide.factor(getFn)} if you do not need to configure + * your service in a provider. * * @param {string} name The name of the instance. * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for * `$provide.provider(name, {$get: $getFn})`. * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + *
+ *   $provide.factory('ping', ['$http', function($http) {
+ *     return function ping() {
+ *       return $http.send('/ping');
+ *     };
+ *   }]);
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller('Ctrl', ['ping', function(ping) {
+ *     ping();
+ *   }]);
+ * 
*/ @@ -372,11 +421,34 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A service whose instance is created by invoking `constructor` with `new`. A short hand for registering services which use a constructor. + * Register a **service constructor**, which will be invoked with `new` to create the service instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. + * + * You should use {@link AUTO.$provide#service $provide.service(class)} if you define your service + * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}. * * @param {string} name The name of the instance. * @param {Function} constructor A class (constructor function) that will be instantiated. * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using {@link AUTO.$provide#service $provide.service(class)} + * that is defined as a CoffeeScript class. + *
+ *   class Ping
+ *     constructor: (@$http)->
+ *     send: ()=>
+ *       @$http.get('/ping')
+ *  
+ *   $provide.service('ping', ['$http', Ping])
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller 'Ctrl', ['ping', (ping)->
+ *     ping.send()
+ *   ]
+ * 
*/ @@ -386,11 +458,29 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A short hand for configuring services if the `$get` method is a constant. + * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a number, + * an array, an object or a function. This is short for registering a service where its provider's + * `$get` property is a factory function that takes no arguments and returns the **value service**. * + * Value services are similar to constant services, except that they cannot be injected into a module + * configuration function (see {@link angular.Module#config}) but they can be overridden by an Angular + * {@link AUTO.$provide#decorator decorator}. + * * @param {string} name The name of the instance. * @param {*} value The value. * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + *
+ *   $provide.constant('ADMIN_USER', 'admin');
+ *   
+ *   $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *   
+ *   $provide.constant('halfOf', function(value) {
+ *     return value / 2;
+ *   });
+ * 
*/ @@ -400,13 +490,26 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected - * into configuration function (other modules) and it is not interceptable by - * {@link AUTO.$provide#decorator decorator}. + * Register a **constant service**, such as a string, a number, an array, an object or a function, with + * the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be injected + * into a module configuration function (see {@link angular.Module#config}) and it cannot be + * overridden by an Angular {@link AUTO.$provide#decorator decorator}. * * @param {string} name The name of the constant. * @param {*} value The constant value. * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + *
+ *   $provide.constant('SHARD_HEIGHT', 306);
+ *   
+ *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *   
+ *   $provide.constant('double', function(value) {
+ *     return value * 2;
+ *   });
+ * 
*/ @@ -416,17 +519,29 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * Decoration of service, allows the decorator to intercept the service instance creation. The - * returned instance may be the original instance, or a new instance which delegates to the - * original instance. + * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service object + * which replaces or wraps and delegates to the original service. * * @param {string} name The name of the service to decorate. * @param {function()} decorator This function will be invoked when the service needs to be - * instantiated. The function is called using the {@link AUTO.$injector#invoke - * injector.invoke} method and is therefore fully injectable. Local injection arguments: + * instantiated and should return the decorated service instance. The function is called using + * the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: * * * `$delegate` - The original service instance, which can be monkey patched, configured, * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + *
+ *   $provider.decorator('$log', ['$delegate', function($delegate) {
+ *     $delegate.warn = $delegate.error;
+ *     return $delegate;
+ *   }]);
+ * 
*/