aboutsummaryrefslogtreecommitdiffstats
path: root/docs/content/guide/concepts.ngdoc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/content/guide/concepts.ngdoc')
-rw-r--r--docs/content/guide/concepts.ngdoc765
1 files changed, 349 insertions, 416 deletions
diff --git a/docs/content/guide/concepts.ngdoc b/docs/content/guide/concepts.ngdoc
index bbf12b32..d0c2beca 100644
--- a/docs/content/guide/concepts.ngdoc
+++ b/docs/content/guide/concepts.ngdoc
@@ -2,450 +2,383 @@
@name Conceptual Overview
@description
-# Overview
-
-This document gives a quick overview of the main angular components and how they work together.
-These are:
-
- * {@link concepts#startup startup} - bring up hello world
- * {@link concepts#runtime runtime} - overview of angular runtime
- * {@link concepts#scope scope} - the glue between the view and the controller
- * {@link concepts#controller controller} - application behavior
- * {@link concepts#model model} - your application data
- * {@link concepts#view view} - what the user sees
- * {@link concepts#directives directives} - extend HTML vocabulary
- * {@link concepts#filters filters} - format the data in user locale
- * {@link concepts#injector injector} - assembles your application
- * {@link concepts#module module} - configures the injector
- * {@link concepts#angular_namespace `$`} - angular namespace
-
-<a name="startup"></a>
-# Startup
-
-This is how we get the ball rolling (refer to the diagram and example below):
-
-<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png">
-
- 1. The browser loads the HTML and parses it into a DOM
- 2. The browser loads `angular.js` script
- 3. Angular waits for `DOMContentLoaded` event
- 4. Angular looks for {@link api/ng.directive:ngApp ng-app}
- {@link guide/directive directive}, which designates the application boundary
- 5. The {@link guide/module Module} specified in {@link
- api/ng.directive:ngApp ng-app} (if any) is used to configure
- the {@link api/AUTO.$injector $injector}
- 6. The {@link api/AUTO.$injector $injector} is used to create the {@link
- api/ng.$compile $compile} service as well as {@link
- api/ng.$rootScope $rootScope}
- 7. The {@link api/ng.$compile $compile} service is used to compile the DOM and link
- it with {@link api/ng.$rootScope $rootScope}
- 8. The {@link api/ng.directive:ngInit ng-init} {@link
- guide/directive directive} assigns `World` to the `name` property on the {@link guide/scope
- scope}
- 9. The `{{name}}` {@link api/ng.$interpolate interpolates} the expression to
- `Hello World!`
-
-<example>
- <file name="index.html">
- <p ng-init=" name='World' ">Hello {{name}}!</p>
- </file>
-</example>
+There are some concepts within Angular that you should understand before creating your first application.
+This section touches all important parts of Angular really quickly using a simple example.
+However, it won't explain all details.
+For a more in-depth explanation, have a look at the {@link tutorial/ tutorial}.
+| Concept | Description |
+|------------------|------------------------------------------|
+|{@link concepts#template Template} | HTML with additional markup |
+|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
+|{@link concepts#model Model} | the data that is shown to the user and with which the user interacts |
+|{@link concepts#scope Scope} | context where the model is stored so that directives and expressions can access it |
+|{@link concepts#expression Expressions} | access variables and functions from the scope |
+|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
+|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
+|{@link concepts#view View} | what the user sees (the DOM) |
+|{@link concepts#databinding Data Binding} | sync data between the model and the view |
+|{@link concepts#controller Controller} | the business logic behind views |
+|{@link concepts#di Dependency Injection} | Creates and wires objects / functions |
+|{@link concepts#injector Injector} | dependency injection container |
+|{@link concepts#module Module} | configures the Injector |
+|{@link concepts#service Service} | reusable business logic independent of views |
-<a name="runtime"></a>
-# Runtime
-
-<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png">
-
-The diagram and the example below describe how Angular interacts with the browser's event loop.
-
- 1. The browser's event-loop waits for an event to arrive. An event is a user interaction, timer event,
- or network event (response from a server).
- 2. The event's callback gets executed. This enters the JavaScript context. The callback can
- modify the DOM structure.
- 3. Once the callback executes, the browser leaves the JavaScript context and
- re-renders the view based on DOM changes.
-
-Angular modifies the normal JavaScript flow by providing its own event processing loop. This
-splits the JavaScript into classical and Angular execution context. Only operations which are
-applied in Angular execution context will benefit from Angular data-binding, exception handling,
-property watching, etc... You can also use $apply() to enter Angular execution context from JavaScript. Keep in
-mind that in most places (controllers, services) $apply has already been called for you by the
-directive which is handling the event. An explicit call to $apply is needed only when
-implementing custom event callbacks, or when working with third-party library callbacks.
-
- 1. Enter Angular execution context by calling {@link guide/scope scope}`.`{@link
- api/ng.$rootScope.Scope#methods_$apply $apply}`(stimulusFn)`. Where `stimulusFn` is
- the work you wish to do in Angular execution context.
- 2. Angular executes the `stimulusFn()`, which typically modifies application state.
- 3. Angular enters the {@link api/ng.$rootScope.Scope#methods_$digest $digest} loop. The
- loop is made up of two smaller loops which process {@link
- api/ng.$rootScope.Scope#methods_$evalAsync $evalAsync} queue and the {@link
- api/ng.$rootScope.Scope#methods_$watch $watch} list. The {@link
- api/ng.$rootScope.Scope#methods_$digest $digest} loop keeps iterating until the model
- stabilizes, which means that the {@link api/ng.$rootScope.Scope#methods_$evalAsync
- $evalAsync} queue is empty and the {@link api/ng.$rootScope.Scope#methods_$watch
- $watch} list does not detect any changes.
- 4. The {@link api/ng.$rootScope.Scope#methods_$evalAsync $evalAsync} queue is used to
- schedule work which needs to occur outside of current stack frame, but before the browser's
- view render. This is usually done with `setTimeout(0)`, but the `setTimeout(0)` approach
- suffers from slowness and may cause view flickering since the browser renders the view after
- each event.
- 5. The {@link api/ng.$rootScope.Scope#methods_$watch $watch} list is a set of expressions
- which may have changed since last iteration. If a change is detected then the `$watch`
- function is called which typically updates the DOM with the new value.
- 6. Once the Angular {@link api/ng.$rootScope.Scope#methods_$digest $digest} loop finishes
- the execution leaves the Angular and JavaScript context. This is followed by the browser
- re-rendering the DOM to reflect any changes.
-
-
-Here is the explanation of how the `Hello world` example achieves the data-binding effect when the
-user enters text into the text field.
-
- 1. During the compilation phase:
- 1. the {@link api/ng.directive:ngModel ng-model} and {@link
- api/ng.directive:input input} {@link guide/directive
- directive} set up a `keydown` listener on the `<input>` control.
- 2. the {@link api/ng.$interpolate &#123;&#123;name&#125;&#125; } interpolation
- sets up a {@link api/ng.$rootScope.Scope#methods_$watch $watch} to be notified of
- `name` changes.
- 2. During the runtime phase:
- 1. Pressing an '`X`' key causes the browser to emit a `keydown` event on the input control.
- 2. The {@link api/ng.directive:input input} directive
- captures the change to the input's value and calls {@link
- api/ng.$rootScope.Scope#methods_$apply $apply}`("name = 'X';")` to update the
- application model inside the Angular execution context.
- 3. Angular applies the `name = 'X';` to the model.
- 4. The {@link api/ng.$rootScope.Scope#methods_$digest $digest} loop begins
- 5. The {@link api/ng.$rootScope.Scope#methods_$watch $watch} list detects a change
- on the `name` property and notifies the {@link api/ng.$interpolate
- &#123;&#123;name&#125;&#125; } interpolation, which in turn updates the DOM.
- 6. Angular exits the execution context, which in turn exits the `keydown` event and with it
- the JavaScript execution context.
- 7. The browser re-renders the view with update text.
-<example>
- <file name="index.html">
- <input ng-model="name">
- <p>Hello {{name}}!</p>
- </file>
-</example>
+# A first example: Data binding
-<a name="scope"></a>
-#Scope
+In the following we will build a form to calculate the costs of an invoice in different currencies.
-The {@link guide/scope scope} is responsible for detecting changes to the model section and
-provides the execution context for expressions. The scopes are nested in a hierarchical structure
-which closely follow the DOM structure. (See individual directive documentation to see which
-directives cause a creation of new scopes.)
+Let's start with input fields for quantity and cost whose values are multiplied to produce the total of the invoice:
-The following example demonstrates how the `name` {@link guide/expression expression} will evaluate
-into a different value depending on which scope it is evaluated in. The example is followed by
-a diagram depicting the scope boundaries.
-<div class="show-scope">
<example>
<file name="index.html">
- <div ng-controller="GreetCtrl">
- Hello {{name}}!
- </div>
- <div ng-controller="ListCtrl">
- <ol>
- <li ng-repeat="name in names">{{name}}</li>
- </ol>
- </div>
- </file>
- <file name="script.js">
- function GreetCtrl($scope) {
- $scope.name = 'World';
- }
-
- function ListCtrl($scope) {
- $scope.names = ['Igor', 'Misko', 'Vojta'];
- }
- </file>
- <file name="style.css">
- .show-scope .doc-example-live.ng-scope,
- .show-scope .doc-example-live .ng-scope {
- border: 1px solid red;
- margin: 3px;
- }
+ <div ng-init="qty=1;cost=2">
+ <b>Invoice:</b>
+ <div>
+ Quantity: <input type="number" ng-model="qty" required >
+ </div>
+ <div>
+ Costs: <input type="number" ng-model="cost" required >
+ </div>
+ <div>
+ <b>Total:</b> {{qty * cost | currency}}
+ </div>
+ </div>
</file>
</example>
-</div>
-
-<img class="center" src="img/guide/concepts-scope.png">
-
-
-<a name="controller"></a>
-# Controller
-<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png">
-
-A controller is the code behind the view. Its job is to construct the model and publish it to the
-view along with callback methods. The view is a projection of the scope onto the template (the
-HTML). The scope is the glue which marshals the model to the view and forwards the events to the
-controller.
-
-The separation of the controller and the view is important because:
-
- * The controller is written in JavaScript. JavaScript is imperative. Imperative is a good fit
- for specifying application behavior. The controller should not contain any rendering
- information (DOM references or HTML fragments).
- * The view template is written in HTML. HTML is declarative. Declarative is a good fit for
- specifying UI. The View should not contain any behavior.
- * Since the controller is unaware of the view, there could be many views for the same
- controller. This is important for re-skinning, device specific views (i.e. mobile vs desktop),
- and testability.
+Try out the Live Preview above, and then let's walk through the example and describe what's going on.
+
+<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding1.png">
+
+This looks like normal HTML, with some new markup. In Angular, a file like this is called a
+<a name="template">"{@link templates template}"</a>. When Angular starts your application, it parses and
+processes this new markup from the template using the so called <a name="compiler">"{@link compiler compiler}"</a>.
+The loaded, transformed and rendered DOM is then called the <a name="view">"view"</a>.
+
+The first kind of new markup are the so called <a name="directive">"{@link directive directives}"</a>.
+They apply special behavior to attributes or elements in the HTML. In the example above we use the
+{@link api/ng.directive:ngApp `ng-app`} attribute, which is linked to a directive that automatically
+initializes our application. Angular also defines a directive for the {@link api/ng.directive:input `input`}
+element that adds extra behavior to the element. E.g. it is able to automatically validate that the entered
+text is non empty by evaluating the `required` attribute.
+The {@link api/ng.directive:ngModel `ng-model`} directive stores/updates
+the value of the input field into/from a variable and shows the validation state of the input field by
+adding css classes. In the example we use these css classes to mark an empty input field with a red border.
+
+<div class="alert alert-info">
+**Custom directives to access the DOM**: In Angular, the only place where an application touches the DOM is
+ within directives. This is good as artifacts that access the DOM are hard to test.
+ If you need to access the DOM directly you should write a custom directive for this. The
+ {@link directive directives guide} explains how to do this.
+</div>
-<example>
- <file name="index.html">
- <div ng-controller="MyCtrl">
- Hello {{name}}!
- <button ng-click="action()">
- OK
- </button>
- </div>
- </file>
- <file name="script.js">
- function MyCtrl($scope) {
- $scope.action = function() {
- $scope.name = 'OK';
- }
-
- $scope.name = 'World';
- }
+The second kind of new markup are the double curly braces `{{ expression | filter }}`:
+When the compiler encounters this markup, it will replace it with the evaluated value of the markup.
+An <a name="expression">"{@link expression expression}"</a> in a template is a JavaScript-like code snippet that allows
+to read and write variables. Note that those variables are not global variables.
+Just like variables in a JavaScript function live in a scope,
+Angular provides a <a name="scope">"{@link scope scope}"</a> for the variables accessible to expressions.
+The values that are stored in variables on the scope are referred to as the <a name="model">"model"</a>
+in the rest of the documentation.
+Applied to the example above, the markup directs Angular to "take the data we got from the input widgets
+and multiply them together".
+
+The example above also contains a <a name="filter">"{@link dev_guide.templates.filters filter}"</a>.
+A filter formats the value of an expression for display to the user.
+In the example above, the filter {@link api/ng.filter:currency `currency`} formats a number
+into an output that looks like money.
+
+The important thing in the example is that angular provides _live_ bindings:
+Whenever the input values change, the value of the expressions are automatically
+recalculated and the DOM is updated with their values.
+The concept behind this is <a name="databinding">"{@link databinding two-way data binding}"</a>.
+
+
+# Adding UI logic: Controllers
+
+Let's add some more logic to the example to
+allow to enter and calculate the costs in different currencies and also pay the invoice.
+
+<example module="invoice1">
+ <file name="invoice1.js">
+ angular.module('invoice1', [])
+ .controller('InvoiceController', function() {
+ this.qty = 1;
+ this.cost = 2;
+ this.inCurr = 'EUR';
+ this.currencies = ['USD', 'EUR', 'CNY'];
+ this.usdToForeignRates = {
+ USD: 1,
+ EUR: 0.74,
+ CNY: 6.09
+ };
+
+ this.total = function total(outCurr) {
+ return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
+ };
+ this.convertCurrency = function convertCurrency(amount, inCurr, outCurr) {
+ return amount * this.usdToForeignRates[outCurr] * 1 / this.usdToForeignRates[inCurr];
+ };
+ this.pay = function pay() {
+ window.alert("Thanks!");
+ };
+ });
</file>
-</example>
-
-
-<a name="model"></a>
-# Model
-
-<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png">
-
-The model is the data which is merged with the template to produce the view. To be able to
-render the model into the view, the model has to be able to be referenced from the scope. Unlike many
-other frameworks Angular makes no restrictions or requirements on the model. There are no classes
-to inherit from or special accessor methods for accessing or changing the model. The model can be
-primitive, object hash, or a full object Type. In short the model is a plain JavaScript object.
-
-
-<a name="view"></a>
-# View
-
-<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-view.png">
-
-The view is what the user sees. The view begins its life as a template, is merged with the
-model and finally rendered into the browser DOM. Angular takes a very different approach to
-rendering the view compared to most other templating systems.
-
- * **Others** - Most templating systems begin as an HTML string with special templating markup.
- Often the template markup breaks the HTML syntax which means that the template can not be
- edited by an HTML editor. The template string is then parsed by the template engine, and
- merged with the data. The result of the merge is an HTML string. The HTML string is then
- written to the browser using the `.innerHTML`, which causes the browser to render the HTML.
- When the model changes the whole process needs to be repeated. The granularity of the template
- is the granularity of the DOM updates. The key here is that the templating system manipulates
- strings.
- * **Angular** - Angular is different, since its templating system works on DOM objects not on
- strings. The template is still written in an HTML string, but it is HTML (not HTML with
- template sprinkled in.) The browser parses the HTML into the DOM, and the DOM becomes the input to
- the template engine known as the {@link api/ng.$compile compiler}. The compiler
- looks for {@link guide/directive directives} which in turn set up {@link
- api/ng.$rootScope.Scope#methods_$watch watches} on the model. The result is a
- continuously updating view which does not need template model re-merging. Your model becomes
- the single source-of-truth for your view.
-
-<example>
<file name="index.html">
- <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
- <input ng-model="list" ng-list> <br>
- <input ng-model="list" ng-list> <br>
- <pre>list={{list}}</pre> <br>
- <ol>
- <li ng-repeat="item in list">
- {{item}}
- </li>
- </ol>
- </div>
+ <div ng-controller="InvoiceController as invoice">
+ <b>Invoice:</b>
+ <div>
+ Quantity: <input type="number" ng-model="invoice.qty" required >
+ </div>
+ <div>
+ Costs: <input type="number" ng-model="invoice.cost" required >
+ <select ng-model="invoice.inCurr">
+ <option ng-repeat="c in invoice.currencies">{{c}}</option>
+ </select>
+ </div>
+ <div>
+ <b>Total:</b>
+ <span ng-repeat="c in invoice.currencies">
+ {{invoice.total(c) | currency:c}}
+ </span>
+ <button ng-click="invoice.pay()">Pay</button>
+ </div>
+ </div>
</file>
</example>
-
-<a name="directives"></a>
-# Directives
-
-A directive is a behavior or DOM transformation which is triggered by the presence of a custom attribute,
-element name, class name or comment. A directive allows you to extend the HTML vocabulary in a
-declarative fashion. Following is an example which enables data-binding for the `contenteditable`
-in HTML.
-
-<example module="directive">
- <file name="script.js">
- angular.module('directive', []).directive('contenteditable', function() {
- return {
- require: 'ngModel',
- link: function(scope, elm, attrs, ctrl) {
- // view -> model
- elm.on('blur', function() {
- scope.$apply(function() {
- ctrl.$setViewValue(elm.html());
- });
- });
-
- // model -> view
- ctrl.$render = function(value) {
- elm.html(value);
- };
-
- // load init value from DOM
- ctrl.$setViewValue(elm.html());
+What changed?
+
+First, there is a new JavaScript file that contains a so called <a name="controller">"{@link controller controller}"</a>.
+More exactly, the file contains a constructor function that creates the actual controller instance.
+The purpose of controllers is to expose variables and functionality to expressions and directives.
+
+Besides the new file that contains the controller code we also added a
+{@link api/ng.directive:ngController `ng-controller`} directive to the HTML.
+This directive tells angular that the new `InvoiceController` is responsible for the element with the directive
+and all of the element's children.
+The syntax `InvoiceController as invoice` tells Angular to instantiate the controller
+and save it in the variable `invoice` in the current scope.
+
+We also changed all expressions in the page to read and write variables within that
+controller instance by prefixing them with `invoice.` . The possible currencies are defined in the controller
+and added to the template using {@link api/ng.directive:ngRepeat `ng-repeat`}.
+As the controller contains a `total` function
+we are also able to bind the result of that function to the DOM using `{{ invoice.total(...) }}`.
+
+Again, this binding is live, i.e. the DOM will be automatically updated
+whenever the result of the function changes.
+The button to pay the invoice uses the directive {@link api/ng.directive:ngClick `ngClick`}. This will evaluate the
+corresponding expression whenever the button is clicked.
+
+In the new JavaScript file we are also creating a {@link concepts#module module}
+at which we register the controller. We will talk about modules in the next section.
+
+The following graphic shows how everything works together after we introduced the controller:
+
+<img style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding2.png">
+
+# View independent business logic: Services
+
+Right now, the `InvoiceController` contains all logic of our example. When the application grows it
+is a good practise to move view independent logic from the controller into a so called
+<a name="service">"{@link dev_guide.services service}"</a>, so it can be reused by other parts
+of the application as well. Later on, we could also change that service to load the exchange rates
+from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
+
+Let's refactor our example and move the currency conversion into a service in another file:
+
+<example module="invoice2">
+ <file name="finance2.js">
+ angular.module('finance2', [])
+ .factory('currencyConverter', function() {
+ var currencies = ['USD', 'EUR', 'CNY'],
+ usdToForeignRates = {
+ USD: 1,
+ EUR: 0.74,
+ CNY: 6.09
+ };
+ return {
+ currencies: currencies,
+ convert: convert
+ };
+
+ function convert(amount, inCurr, outCurr) {
+ return amount * usdToForeignRates[outCurr] * 1 / usdToForeignRates[inCurr];
}
- };
- });
- </file>
- <file name="index.html">
- <div contentEditable="true" ng-model="content">Edit Me</div>
- <pre>model = {{content}}</pre>
+ });
</file>
- <file name="style.css">
- div[contentEditable] {
- cursor: pointer;
- background-color: #D0D0D0;
- margin-bottom: 1em;
- padding: 1em;
- }
+ <file name="invoice2.js">
+ angular.module('invoice2', ['finance2'])
+ .controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
+ this.qty = 1;
+ this.cost = 2;
+ this.inCurr = 'EUR';
+ this.currencies = currencyConverter.currencies;
+
+ this.total = function total(outCurr) {
+ return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
+ };
+ this.pay = function pay() {
+ window.alert("Thanks!");
+ };
+ }]);
</file>
-</example>
-
-<a name="filters"></a>
-# Filters
-
-{@link api/ng.$filter Filters} perform data transformation. Typically
-they are used in conjunction with the locale to format the data in locale specific output.
-They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
-
-<example>
<file name="index.html">
- <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
- Number formatting: {{ 1234567890 | number }} <br>
- array filtering <input ng-model="predicate">
- {{ list | filter:predicate | json }}
- </div>
+ <div ng-controller="InvoiceController as invoice">
+ <b>Invoice:</b>
+ <div>
+ Quantity: <input type="number" ng-model="invoice.qty" required >
+ </div>
+ <div>
+ Costs: <input type="number" ng-model="invoice.cost" required >
+ <select ng-model="invoice.inCurr">
+ <option ng-repeat="c in invoice.currencies">{{c}}</option>
+ </select>
+ </div>
+ <div>
+ <b>Total:</b>
+ <span ng-repeat="c in invoice.currencies">
+ {{invoice.total(c) | currency:c}}
+ </span>
+ <button ng-click="invoice.pay()">Pay</button>
+ </div>
+ </div>
</file>
</example>
-
-<a name="module"></a>
-<a name="injector"></a>
-# Modules and the Injector
-
-<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png">
-
-The {@link api/AUTO.$injector injector} is a service locator. There is a single
-{@link api/AUTO.$injector injector} per Angular {@link
-api/ng.directive:ngApp application}. The {@link
-api/AUTO.$injector injector} provides a way to look up an object instance by its
-name. The injector keeps an internal cache of all objects so that repeated calls to get the same
-object name result in the same instance. If the object does not exist, then the {@link
-api/AUTO.$injector injector} asks the instance factory to create a new instance.
-
-A {@link api/angular.Module module} is a way to configure the injector's instance factory, known
-as a {@link api/AUTO.$provide provider}.
-
-<pre>
- // Create a module
- var myModule = angular.module('myModule', [])
-
- // Configure the injector
- myModule.factory('serviceA', function() {
- return {
- // instead of {}, put your object creation here
- };
- });
-
- // create an injector and configure it from 'myModule'
- var $injector = angular.injector(['myModule']);
-
- // retrieve an object from the injector by name
- var serviceA = $injector.get('serviceA');
-
- // always true because of instance cache
- $injector.get('serviceA') === $injector.get('serviceA');
-</pre>
-
-
-But the real magic of the {@link api/AUTO.$injector injector} is that it can be
-used to {@link api/AUTO.$injector#methods_invoke call} methods and {@link
-api/AUTO.$injector#methods_instantiate instantiate} types. This subtle feature is what
-allows the methods and types to ask for their dependencies instead of having to look for them.
-
-<pre>
- // You write functions such as this one.
- function doSomething(serviceA, serviceB) {
- // do something here.
- }
-
- // Angular provides the injector for your application
- var $injector = ...;
-
- ///////////////////////////////////////////////
- // the old-school way of getting dependencies.
- var serviceA = $injector.get('serviceA');
- var serviceB = $injector.get('serviceB');
-
- // now call the function
- doSomething(serviceA, serviceB);
-
- ///////////////////////////////////////////////
- // the cool way of getting dependencies.
- // the $injector will supply the arguments to the function automatically
- $injector.invoke(doSomething); // This is how the framework calls your functions
-</pre>
-
-Notice that the only thing you needed to write was the function, and list the dependencies in the
-function arguments. When angular calls the function, it will use the {@link
-api/AUTO.$injector#methods_invoke call} which will automatically fill the function
-arguments.
-
-Examine the `ClockCtrl` below, and notice how it lists the dependencies in the constructor. When the
-{@link api/ng.directive:ngController ng-controller} instantiates
-the controller it automatically provides the dependencies. There is no need to create
-dependencies, look for dependencies, or even get a reference to the injector.
-
-<example module="timeExampleModule">
- <file name="index.html">
- <div ng-controller="ClockCtrl">
- Current time is: {{ time.now }}
- </div>
+<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-service.png">
+
+What changed?
+We moved the `convertCurrency` function and the definition of the existing currencies
+into the new file `finance.js`. But how does the controller
+get a hold of the now separated function?
+
+This is where <a name="di">"{@link di Dependency Injection}"</a> comes into play.
+Dependency Injection (DI) is a software design pattern that
+deals with how objects and functions get created and how they get a hold of their dependencies.
+Everything within Angular (directives, filters, controllers,
+services, ...) is created and wired using dependency injection. Within Angular,
+the DI container is called the <a name="injector">"{@link di injector}"</a>.
+
+To use DI, there needs to be a place where all the things that should work together are registered.
+In Angular, this is the purpose of the so called <a name="module">"{@link module modules}"</a>.
+When Angular starts, it will use the configuration of the module with the name defined by the `ng-app` directive,
+including the configuration of all modules that this module depends on.
+
+In the example above:
+The template contains the directive `ng-app="invoice"`. This tells Angular
+to use the `invoice` module as the main module for the application.
+The code snippet `angular.module('invoice', ['finance'])` specifies that the `invoice` module depends on the
+`finance` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service.
+
+Now that Angular knows of all the parts of the application, it needs to create them.
+In the previous section we saw that controllers are created using a factory function.
+For services there are multiple ways to define their factory
+(see the {@link dev_guide.services service guide}).
+In the example above, we are using a function that returns the `currencyConverter` function as the factory
+for the service.
+
+Back to the initial question: How does the `InvoiceController` get a reference to the `currencyConverter` function?
+In Angular, this is done by simply defining arguments on the constructor function. With this, the injector
+is able to create the objects in the right order and pass the previously created objects into the
+factories of the objects that depend on them.
+In our example, the `InvoiceController` has an argument named `currencyConverter`. By this, Angular knows about the
+dependency between the controller and the service and calls the controller with the service instance as argument.
+
+The last thing that changed in the example between the previous section and this section is that we
+now pass an array to the `module.controller` function, instead of a plain function. The array first
+contains the names of the service dependencies that the controller needs. The last entry
+in the array is the controller constructor function.
+Angular uses this array syntax to define the dependencies so that the DI also works after minifying
+the code, which will most probably rename the argument name of the controller constructor function
+to something shorter like `a`.
+
+# Accessing the backend
+
+Let's finish our example by fetching the exchange rates from the Yahoo Finance API.
+The following example shows how this is done with Angular:
+
+<example module="invoice3">
+ <file name="invoice3.js">
+ angular.module('invoice3', ['finance3'])
+ .controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
+ this.qty = 1;
+ this.cost = 2;
+ this.inCurr = 'EUR';
+ this.currencies = currencyConverter.currencies;
+
+ this.total = function total(outCurr) {
+ return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
+ };
+ this.pay = function pay() {
+ window.alert("Thanks!");
+ };
+ }]);
</file>
- <file name="script.js">
- angular.module('timeExampleModule', []).
- // Declare new object called time,
- // which will be available for injection
- factory('time', function($timeout) {
- var time = {};
-
- (function tick() {
- time.now = new Date().toString();
- $timeout(tick, 1000);
- })();
- return time;
- });
+ <file name="finance3.js">
+ angular.module('finance3', [])
+ .factory('currencyConverter', ['$http', function($http) {
+ var YAHOO_FINANCE_URL_PATTERN =
+ 'http://query.yahooapis.com/v1/public/yql?q=select * from '+
+ 'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
+ 'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK',
+ currencies = ['USD', 'EUR', 'CNY'],
+ usdToForeignRates = {};
+ refresh();
+ return {
+ currencies: currencies,
+ convert: convert,
+ refresh: refresh
+ };
+
+ function convert(amount, inCurr, outCurr) {
+ return amount * usdToForeignRates[outCurr] * 1 / usdToForeignRates[inCurr];
+ }
- // Notice that you can simply ask for time
- // and it will be provided. No need to look for it.
- function ClockCtrl($scope, time) {
- $scope.time = time;
- }
+ function refresh() {
+ var url = YAHOO_FINANCE_URL_PATTERN.
+ replace('PAIRS', 'USD' + currencies.join('","USD'));
+ return $http.jsonp(url).success(function(data) {
+ var newUsdToForeignRates = {};
+ angular.forEach(data.query.results.rate, function(rate) {
+ var currency = rate.id.substring(3,6);
+ newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);
+ });
+ usdToForeignRates = newUsdToForeignRates;
+ });
+ }
+ }]);
+ </file>
+ <file name="index.html">
+ <div ng-controller="InvoiceController as invoice">
+ <b>Invoice:</b>
+ <div>
+ Quantity: <input type="number" ng-model="invoice.qty" required >
+ </div>
+ <div>
+ Costs: <input type="number" ng-model="invoice.cost" required >
+ <select ng-model="invoice.inCurr">
+ <option ng-repeat="c in invoice.currencies">{{c}}</option>
+ </select>
+ </div>
+ <div>
+ <b>Total:</b>
+ <span ng-repeat="c in invoice.currencies">
+ {{invoice.total(c) | currency:c}}
+ </span>
+ <button ng-click="invoice.pay()">Pay</button>
+ </div>
+ </div>
</file>
</example>
+What changed?
+Our `currencyConverter` service of the `finance` module now uses the
+{@link api/ng.$http $http} service, a builtin service provided by Angular
+for accessing the backend. It is a wrapper around [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
+and [JSONP](http://en.wikipedia.org/wiki/JSONP) transports. Details can be found in the api docs of that service.
-<a name="angular_namespace"></a>
-# Angular Namespace
-
-To prevent accidental name collision, Angular prefixes names of objects which could potentially
-collide with `$`. Please do not use the `$` prefix in your code as it may accidentally collide
-with Angular code.