aboutsummaryrefslogtreecommitdiffstats
path: root/docs/angular.service.ngdoc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/angular.service.ngdoc')
-rw-r--r--docs/angular.service.ngdoc159
1 files changed, 159 insertions, 0 deletions
diff --git a/docs/angular.service.ngdoc b/docs/angular.service.ngdoc
new file mode 100644
index 00000000..30fb8512
--- /dev/null
+++ b/docs/angular.service.ngdoc
@@ -0,0 +1,159 @@
+@workInProgress
+@ngdoc overview
+@name angular.service
+
+@description
+# Overview
+Services are substituable objects, which are wired together using dependency injection.
+Each service could have dependencies (other services), which are passed in constructor.
+Because JS is dynamicaly typed language, dependency injection can not use static types
+to satisfy these dependencies, so each service must explicitely define its dependencies.
+This is done by `$inject` property.
+
+For now, life time of all services is the same as the life time of page.
+
+
+# Built-in services
+The Angular framework provides a standard set of services for common operations.
+You can write your own services and rewrite these standard services as well.
+Like other core angular variables, the built-in services always start with $.
+
+ * `angular.service.$browser`
+ * `angular.service.$window`
+ * `angular.service.$document`
+ * `angular.service.$location`
+ * `angular.service.$log`
+ * `angular.service.$exceptionHandler`
+ * `angular.service.$hover`
+ * `angular.service.$invalidWidgets`
+ * `angular.service.$route`
+ * `angular.service.$xhr`
+ * `angular.service.$xhr.error`
+ * `angular.service.$xhr.bulk`
+ * `angular.service.$xhr.cache`
+ * `angular.service.$resource`
+ * `angular.service.$cookies`
+ * `angular.service.$cookieStore`
+
+# Writing your own custom services
+Angular provides only set of basic services, so you will probably need to write your custom
+service very soon. To do so, you need to write a factory function and register this function
+to angular's dependency injector. This factory function must return an object - your service
+(it is not called with new operator).
+
+**angular.service** has three parameters:
+
+ - `{string} name` - Name of the service
+ - `{function()} factory` - Factory function (called just once by DI)
+ - `{Object} config` - Hash of configuration (`$inject`, `$creation`)
+
+If your service requires - depends on other services, you need to specify them
+in config hash - property $inject. This property is an array of strings (service names).
+These dependencies will be passed as parameters to the factory function by DI.
+This approach is very useful when testing, as you can inject mocks/stubs/dummies.
+
+Here is an example of very simple service. This service requires $window service (it's
+passed as a parameter to factory function) and it's just a function.
+
+This service simple stores all notifications and after third one, it displays all of them by
+window alert.
+<pre>
+ angular.service('notify', function(win) {
+ var msgs = [];
+ return function(msg) {
+ msgs.push(msg);
+ if (msgs.length == 3) {
+ win.alert(msgs.join("\n"));
+ msgs = [];
+ }
+ };
+ }, {$inject: ['$window']});
+</pre>
+
+And here is a unit test for this service. We use Jasmine spy (mock) instead of real browser's alert.
+<pre>
+var mock, notify;
+
+beforeEach(function() {
+ mock = {alert: jasmine.createSpy()};
+ notify = angular.service('notify')(mock);
+});
+
+it('should not alert first two notifications', function() {
+ notify('one');
+ notify('two');
+ expect(mock.alert).not.toHaveBeenCalled();
+});
+
+it('should alert all after third notification', function() {
+ notify('one');
+ notify('two');
+ notify('three');
+ expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
+});
+
+it('should clear messages after alert', function() {
+ notify('one');
+ notify('two');
+ notify('third');
+ notify('more');
+ notify('two');
+ notify('third');
+ expect(mock.alert.callCount).toEqual(2);
+ expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]);
+});
+</pre>
+
+# Injecting services into controllers
+Using services in a controllers is very similar to using service in other service.
+Again, we will use dependency injection.
+
+JavaScript is dynamic language, so DI is not able to figure out which services to inject by
+static types (like in static typed languages). Therefore you must specify the service name
+by the `$inject` property - it's an array that contains strings with names of services to be
+injected. The name must match the id that service has been registered as with angular.
+The order of the services in the array matters, because this order will be used when calling
+the factory function with injected parameters. The names of parameters in factory function
+don't matter, but by convention they match the service ids.
+<pre>
+function myController($loc, $log) {
+ this.firstMethod = function() {
+ // use $location service
+ $loc.setHash();
+ };
+ this.secondMethod = function() {
+ // use $log service
+ $log.info('...');
+ };
+}
+// which services to inject ?
+myController.$inject = ['$location', '$log'];
+</pre>
+
+@example
+<script type="text/javascript">
+ angular.service('notify', function(win) {
+ var msgs = [];
+ return function(msg) {
+ msgs.push(msg);
+ if (msgs.length == 3) {
+ win.alert(msgs.join("\n"));
+ msgs = [];
+ }
+ };
+ }, {$inject: ['$window']});
+
+ function myController(notifyService) {
+ this.callNotify = function(msg) {
+ notifyService(msg);
+ };
+ }
+
+ myController.$inject = ['notify'];
+</script>
+
+<div ng:controller="myController">
+<p>Let's try this simple notify service, injected into the controller...</p>
+<input ng:init="message='test'" type="text" name="message" />
+<button ng:click="callNotify(message);">NOTIFY</button>
+</div>