blob: 3af47eae1e0183c8e87e1a4b27da03ac243e1524 [file]
<a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/concepts.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this doc</a>
<h1 id="conceptual-overview">Conceptual Overview</h1>
<p>This section briefly touches on all of the important parts of AngularJS using a simple example.
For a more in-depth explanation, see the <a href="tutorial/">tutorial</a>.</p>
<table>
<thead>
<tr>
<th>Concept</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="guide/concepts#template">Template</a></td>
<td>HTML with additional markup</td>
</tr>
<tr>
<td><a href="guide/concepts#directive">Directives</a></td>
<td>extend HTML with custom attributes and elements</td>
</tr>
<tr>
<td><a href="guide/concepts#model">Model</a></td>
<td>the data that is shown to the user and with which the user interacts</td>
</tr>
<tr>
<td><a href="guide/concepts#scope">Scope</a></td>
<td>context where the model is stored so that controllers, directives and expressions can access it</td>
</tr>
<tr>
<td><a href="guide/concepts#expression">Expressions</a></td>
<td>access variables and functions from the scope</td>
</tr>
<tr>
<td><a href="guide/concepts#compiler">Compiler</a></td>
<td>parses the template and instantiates directives and expressions</td>
</tr>
<tr>
<td><a href="guide/concepts#filter">Filter</a></td>
<td>formats the value of an expression for display to the user</td>
</tr>
<tr>
<td><a href="guide/concepts#view">View</a></td>
<td>what the user sees (the DOM)</td>
</tr>
<tr>
<td><a href="guide/concepts#databinding">Data Binding</a></td>
<td>sync data between the model and the view</td>
</tr>
<tr>
<td><a href="guide/concepts#controller">Controller</a></td>
<td>the business logic behind views</td>
</tr>
<tr>
<td><a href="guide/concepts#di">Dependency Injection</a></td>
<td>Creates and wires objects / functions</td>
</tr>
<tr>
<td><a href="guide/concepts#injector">Injector</a></td>
<td>dependency injection container</td>
</tr>
<tr>
<td><a href="guide/concepts#module">Module</a></td>
<td>configures the Injector</td>
</tr>
<tr>
<td><a href="guide/concepts#service">Service</a></td>
<td>reusable business logic independent of views</td>
</tr>
</tbody>
</table>
<h2 id="a-first-example-data-binding">A first example: Data binding</h2>
<p>In the following example we will build a form to calculate the costs of an invoice in different currencies.</p>
<p>Let&#39;s start with input fields for quantity and cost whose values are multiplied to produce the total of the invoice:</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-guide-concepts-1@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-guide-concepts-1"
name="guide-concepts-1"
ng-app-included="true">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-app ng-init=&quot;qty=1;cost=2&quot;&gt;&#10; &lt;b&gt;Invoice:&lt;/b&gt;&#10; &lt;div&gt;&#10; Quantity: &lt;input type=&quot;number&quot; ng-model=&quot;qty&quot; required &gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; Costs: &lt;input type=&quot;number&quot; ng-model=&quot;cost&quot; required &gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; &lt;b&gt;Total:&lt;/b&gt; {{qty * cost | currency}}&#10; &lt;/div&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-guide-concepts-1/index.html" name="example-guide-concepts-1"></iframe>
</div>
</div>
</p>
<p>Try out the Live Preview above, and then let&#39;s walk through the example and describe what&#39;s going on.</p>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding1.png"></p>
<p>This looks like normal HTML, with some new markup. In Angular, a file like this is called a
<a name="template">&quot;<a href="guide/templates">template</a>&quot;</a>. When Angular starts your application, it parses and
processes this new markup from the template using the so called <a name="compiler">&quot;<a href="guide/compiler">compiler</a>&quot;</a>.
The loaded, transformed and rendered DOM is then called the <a name="view">&quot;view&quot;</a>.</p>
<p>The first kind of new markup are the so called <a name="directive">&quot;<a href="guide/directive">directives</a>&quot;</a>.
They apply special behavior to attributes or elements in the HTML. In the example above we use the
<a href="api/ng/directive/ngApp"><code>ng-app</code></a> attribute, which is linked to a directive that automatically
initializes our application. Angular also defines a directive for the <a href="api/ng/directive/input"><code>input</code></a>
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 <code>required</code> attribute.
The <a href="api/ng/directive/ngModel"><code>ng-model</code></a> 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.</p>
<div class="alert alert-info">
<strong>Custom directives to access the DOM</strong>: 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
<a href="guide/directive">directives guide</a> explains how to do this.
</div>
<p>The second kind of new markup are the double curly braces <code>{{ expression | filter }}</code>:
When the compiler encounters this markup, it will replace it with the evaluated value of the markup.
An <a name="expression">&quot;<a href="guide/expression">expression</a>&quot;</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">&quot;<a href="guide/scope">scope</a>&quot;</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">&quot;model&quot;</a>
in the rest of the documentation.
Applied to the example above, the markup directs Angular to &quot;take the data we got from the input widgets
and multiply them together&quot;.</p>
<p>The example above also contains a <a name="filter">&quot;<a href="guide/filter">filter</a>&quot;</a>.
A filter formats the value of an expression for display to the user.
In the example above, the filter <a href="api/ng/filter/currency"><code>currency</code></a> formats a number
into an output that looks like money.</p>
<p>The important thing in the example is that angular provides <em>live</em> 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">&quot;<a href="guide/databinding">two-way data binding</a>&quot;</a>.</p>
<h2 id="adding-ui-logic-controllers">Adding UI logic: Controllers</h2>
<p>Let&#39;s add some more logic to the example that allows us to enter and calculate the costs in
different currencies and also pay the invoice.</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-guide-concepts-2@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-guide-concepts-2"
name="guide-concepts-2"
ng-app-included="true">
<div class="runnable-example-file"
name="invoice1.js"
language="js"
type="js">
<pre><code>angular.module(&#39;invoice1&#39;, [])&#10; .controller(&#39;InvoiceController&#39;, function() {&#10; this.qty = 1;&#10; this.cost = 2;&#10; this.inCurr = &#39;EUR&#39;;&#10; this.currencies = [&#39;USD&#39;, &#39;EUR&#39;, &#39;CNY&#39;];&#10; this.usdToForeignRates = {&#10; USD: 1,&#10; EUR: 0.74,&#10; CNY: 6.09&#10; };&#10;&#10; this.total = function total(outCurr) {&#10; return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);&#10; };&#10; this.convertCurrency = function convertCurrency(amount, inCurr, outCurr) {&#10; return amount * this.usdToForeignRates[outCurr] / this.usdToForeignRates[inCurr];&#10; };&#10; this.pay = function pay() {&#10; window.alert(&quot;Thanks!&quot;);&#10; };&#10; });</code></pre>
</div>
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-app=&quot;invoice1&quot; ng-controller=&quot;InvoiceController as invoice&quot;&gt;&#10; &lt;b&gt;Invoice:&lt;/b&gt;&#10; &lt;div&gt;&#10; Quantity: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.qty&quot; required &gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; Costs: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.cost&quot; required &gt;&#10; &lt;select ng-model=&quot;invoice.inCurr&quot;&gt;&#10; &lt;option ng-repeat=&quot;c in invoice.currencies&quot;&gt;{{c}}&lt;/option&gt;&#10; &lt;/select&gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; &lt;b&gt;Total:&lt;/b&gt;&#10; &lt;span ng-repeat=&quot;c in invoice.currencies&quot;&gt;&#10; {{invoice.total(c) | currency:c}}&#10; &lt;/span&gt;&#10; &lt;button class=&quot;btn&quot; ng-click=&quot;invoice.pay()&quot;&gt;Pay&lt;/button&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-guide-concepts-2/index.html" name="example-guide-concepts-2"></iframe>
</div>
</div>
</p>
<p>What changed?</p>
<p>First, there is a new JavaScript file that contains a so called <a name="controller">&quot;<a href="guide/controller">controller</a>&quot;</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.</p>
<p>Besides the new file that contains the controller code we also added a
<a href="api/ng/directive/ngController"><code>ng-controller</code></a> directive to the HTML.
This directive tells angular that the new <code>InvoiceController</code> is responsible for the element with the directive
and all of the element&#39;s children.
The syntax <code>InvoiceController as invoice</code> tells Angular to instantiate the controller
and save it in the variable <code>invoice</code> in the current scope.</p>
<p>We also changed all expressions in the page to read and write variables within that
controller instance by prefixing them with <code>invoice.</code> . The possible currencies are defined in the controller
and added to the template using <a href="api/ng/directive/ngRepeat"><code>ng-repeat</code></a>.
As the controller contains a <code>total</code> function
we are also able to bind the result of that function to the DOM using <code>{{ invoice.total(...) }}</code>.</p>
<p>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 <a href="api/ng/directive/ngClick"><code>ngClick</code></a>. This will evaluate the
corresponding expression whenever the button is clicked.</p>
<p>In the new JavaScript file we are also creating a <a href="guide/concepts#module">module</a>
at which we register the controller. We will talk about modules in the next section.</p>
<p>The following graphic shows how everything works together after we introduced the controller:</p>
<p><img style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding2.png"></p>
<h2 id="view-independent-business-logic-services">View independent business logic: Services</h2>
<p>Right now, the <code>InvoiceController</code> contains all logic of our example. When the application grows it
is a good practice to move view independent logic from the controller into a so called
<a name="service">&quot;<a href="guide/services">service</a>&quot;</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.</p>
<p>Let&#39;s refactor our example and move the currency conversion into a service in another file:</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-guide-concepts-21@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-guide-concepts-21"
name="guide-concepts-2"
ng-app-included="true">
<div class="runnable-example-file"
name="finance2.js"
language="js"
type="js">
<pre><code>angular.module(&#39;finance2&#39;, [])&#10; .factory(&#39;currencyConverter&#39;, function() {&#10; var currencies = [&#39;USD&#39;, &#39;EUR&#39;, &#39;CNY&#39;];&#10; var usdToForeignRates = {&#10; USD: 1,&#10; EUR: 0.74,&#10; CNY: 6.09&#10; };&#10; var convert = function (amount, inCurr, outCurr) {&#10; return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];&#10; };&#10;&#10; return {&#10; currencies: currencies,&#10; convert: convert&#10; };&#10; });</code></pre>
</div>
<div class="runnable-example-file"
name="invoice2.js"
language="js"
type="js">
<pre><code>angular.module(&#39;invoice2&#39;, [&#39;finance2&#39;])&#10; .controller(&#39;InvoiceController&#39;, [&#39;currencyConverter&#39;, function(currencyConverter) {&#10; this.qty = 1;&#10; this.cost = 2;&#10; this.inCurr = &#39;EUR&#39;;&#10; this.currencies = currencyConverter.currencies;&#10;&#10; this.total = function total(outCurr) {&#10; return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);&#10; };&#10; this.pay = function pay() {&#10; window.alert(&quot;Thanks!&quot;);&#10; };&#10; }]);</code></pre>
</div>
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-app=&quot;invoice2&quot; ng-controller=&quot;InvoiceController as invoice&quot;&gt;&#10; &lt;b&gt;Invoice:&lt;/b&gt;&#10; &lt;div&gt;&#10; Quantity: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.qty&quot; required &gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; Costs: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.cost&quot; required &gt;&#10; &lt;select ng-model=&quot;invoice.inCurr&quot;&gt;&#10; &lt;option ng-repeat=&quot;c in invoice.currencies&quot;&gt;{{c}}&lt;/option&gt;&#10; &lt;/select&gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; &lt;b&gt;Total:&lt;/b&gt;&#10; &lt;span ng-repeat=&quot;c in invoice.currencies&quot;&gt;&#10; {{invoice.total(c) | currency:c}}&#10; &lt;/span&gt;&#10; &lt;button class=&quot;btn&quot; ng-click=&quot;invoice.pay()&quot;&gt;Pay&lt;/button&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-guide-concepts-21/index.html" name="example-guide-concepts-21"></iframe>
</div>
</div>
</p>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-service.png"></p>
<p>What changed?
We moved the <code>convertCurrency</code> function and the definition of the existing currencies
into the new file <code>finance.js</code>. But how does the controller
get a hold of the now separated function?</p>
<p>This is where <a name="di">&quot;<a href="guide/di">Dependency Injection</a>&quot;</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">&quot;<a href="guide/di">injector</a>&quot;</a>.</p>
<p>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">&quot;<a href="guide/module">modules</a>&quot;</a>.
When Angular starts, it will use the configuration of the module with the name defined by the <code>ng-app</code> directive,
including the configuration of all modules that this module depends on.</p>
<p>In the example above:
The template contains the directive <code>ng-app=&quot;invoice2&quot;</code>. This tells Angular
to use the <code>invoice2</code> module as the main module for the application.
The code snippet <code>angular.module(&#39;invoice2&#39;, [&#39;finance2&#39;])</code> specifies that the <code>invoice2</code> module depends on the
<code>finance2</code> module. By this, Angular uses the <code>InvoiceController</code> as well as the <code>currencyConverter</code> service.</p>
<p>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 <a href="guide/services">service guide</a>).
In the example above, we are using a function that returns the <code>currencyConverter</code> function as the factory
for the service.</p>
<p>Back to the initial question: How does the <code>InvoiceController</code> get a reference to the <code>currencyConverter</code> 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 <code>InvoiceController</code> has an argument named <code>currencyConverter</code>. By this, Angular knows about the
dependency between the controller and the service and calls the controller with the service instance as argument.</p>
<p>The last thing that changed in the example between the previous section and this section is that we
now pass an array to the <code>module.controller</code> 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 <code>a</code>.</p>
<h2 id="accessing-the-backend">Accessing the backend</h2>
<p>Let&#39;s finish our example by fetching the exchange rates from the Yahoo Finance API.
The following example shows how this is done with Angular:</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-guide-concepts-3@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-guide-concepts-3"
name="guide-concepts-3"
ng-app-included="true">
<div class="runnable-example-file"
name="invoice3.js"
language="js"
type="js">
<pre><code>angular.module(&#39;invoice3&#39;, [&#39;finance3&#39;])&#10; .controller(&#39;InvoiceController&#39;, [&#39;currencyConverter&#39;, function(currencyConverter) {&#10; this.qty = 1;&#10; this.cost = 2;&#10; this.inCurr = &#39;EUR&#39;;&#10; this.currencies = currencyConverter.currencies;&#10;&#10; this.total = function total(outCurr) {&#10; return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);&#10; };&#10; this.pay = function pay() {&#10; window.alert(&quot;Thanks!&quot;);&#10; };&#10; }]);</code></pre>
</div>
<div class="runnable-example-file"
name="finance3.js"
language="js"
type="js">
<pre><code>angular.module(&#39;finance3&#39;, [])&#10; .factory(&#39;currencyConverter&#39;, [&#39;$http&#39;, function($http) {&#10; var YAHOO_FINANCE_URL_PATTERN =&#10; &#39;http://query.yahooapis.com/v1/public/yql?q=select * from &#39;+&#10; &#39;yahoo.finance.xchange where pair in (&quot;PAIRS&quot;)&amp;format=json&amp;&#39;+&#10; &#39;env=store://datatables.org/alltableswithkeys&amp;callback=JSON_CALLBACK&#39;;&#10; var currencies = [&#39;USD&#39;, &#39;EUR&#39;, &#39;CNY&#39;];&#10; var usdToForeignRates = {};&#10;&#10; var convert = function (amount, inCurr, outCurr) {&#10; return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];&#10; };&#10;&#10; var refresh = function() {&#10; var url = YAHOO_FINANCE_URL_PATTERN.&#10; replace(&#39;PAIRS&#39;, &#39;USD&#39; + currencies.join(&#39;&quot;,&quot;USD&#39;));&#10; return $http.jsonp(url).success(function(data) {&#10; var newUsdToForeignRates = {};&#10; angular.forEach(data.query.results.rate, function(rate) {&#10; var currency = rate.id.substring(3,6);&#10; newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);&#10; });&#10; usdToForeignRates = newUsdToForeignRates;&#10; });&#10; };&#10;&#10; refresh();&#10;&#10; return {&#10; currencies: currencies,&#10; convert: convert,&#10; refresh: refresh&#10; };&#10; }]);</code></pre>
</div>
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div ng-app=&quot;invoice3&quot; ng-controller=&quot;InvoiceController as invoice&quot;&gt;&#10; &lt;b&gt;Invoice:&lt;/b&gt;&#10; &lt;div&gt;&#10; Quantity: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.qty&quot; required &gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; Costs: &lt;input type=&quot;number&quot; ng-model=&quot;invoice.cost&quot; required &gt;&#10; &lt;select ng-model=&quot;invoice.inCurr&quot;&gt;&#10; &lt;option ng-repeat=&quot;c in invoice.currencies&quot;&gt;{{c}}&lt;/option&gt;&#10; &lt;/select&gt;&#10; &lt;/div&gt;&#10; &lt;div&gt;&#10; &lt;b&gt;Total:&lt;/b&gt;&#10; &lt;span ng-repeat=&quot;c in invoice.currencies&quot;&gt;&#10; {{invoice.total(c) | currency:c}}&#10; &lt;/span&gt;&#10; &lt;button class=&quot;btn&quot; ng-click=&quot;invoice.pay()&quot;&gt;Pay&lt;/button&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-guide-concepts-3/index.html" name="example-guide-concepts-3"></iframe>
</div>
</div>
</p>
<p>What changed?
Our <code>currencyConverter</code> service of the <code>finance</code> module now uses the <a href="api/ng/service/$http"><code>$http</code></a>, a
built-in service provided by Angular for accessing a server backend. <code>$http</code> is a wrapper around
<a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a>
and <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> transports.</p>