Update everything

This commit is contained in:
Colin Frei 2013-04-07 10:12:25 +02:00
parent bf368181a4
commit 72a485d6e8
319 changed files with 67958 additions and 13948 deletions

View file

@ -0,0 +1,101 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>Overview</h2>
<p>This page explains the Angular initialization process and how you can manually initialize Angular
if necessary.</p>
<h2>Angular <code>&lt;script&gt;</code> Tag</h2>
<p>This example shows the recommended path for integrating Angular with what we call automatic
initialization.</p>
<pre class="prettyprint linenums">
&lt;!doctype html&gt;
&lt;html xmlns:ng="http://angularjs.org" ng-app&gt;
&lt;body&gt;
...
&lt;script src="angular.js"&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<ul>
<li>Place the <code>script</code> tag at the bottom of the page. Placing script tags at the end of the page
improves app load time because the HTML loading is not blocked by loading of the <code>angular.js</code>
script. You can get the latest bits from <a href="http://code.angularjs.org">http://code.angularjs.org</a>. Please don't link
your production code to this URL, as it will expose a security hole on your site. For
experimental development linking to our site is fine.
<ul><li>Choose: <code>angular-[version].js</code> for a human-readable file, suitable for development and
debugging.</li>
<li>Choose: <code>angular-[version].min.js</code> for a compressed and obfuscated file, suitable for use in
production.</li></ul></li>
<li><p>Place <code>ng-app</code> to the root of your application, typically on the <code>&lt;html&gt;</code> tag if you want
angular to auto-bootstrap your application.</p>
<pre><code>&lt;html ng-app&gt;
</code></pre></li>
<li><p>If you choose to use the old style directive syntax <code>ng:</code> then include xml-namespace in <code>html</code>
to make IE happy. (This is here for historical reasons, and we no longer recommend use of
<code>ng:</code>.)</p>
<pre><code>&lt;html xmlns:ng="http://angularjs.org"&gt;
</code></pre></li>
</ul>
<h2>Automatic Initialization</h2>
<p>Angular initializes automatically upon <code>DOMContentLoaded</code> event, at which point Angular looks for
the <a href="api/ng.directive:ngApp"><code><code>ng-app</code></code></a> directive which
designates your application root. If the <a href="api/ng.directive:ngApp"><code><code>ng-app</code></code></a> directive is found then Angular
will:</p>
<ul>
<li>load the <a href="guide/module">module</a> associated with the directive.</li>
<li>create the application <a href="api/AUTO.$injector"><code>injector</code></a></li>
<li>compile the DOM treating the <a href="api/ng.directive:ngApp"><code><code>ng-app</code></code></a> directive as the root of the compilation. This allows you to tell it to treat only a
portion of the DOM as an Angular application.</li>
</ul>
<pre class="prettyprint linenums">
&lt;!doctype html&gt;
&lt;html ng-app="optionalModuleName"&gt;
&lt;body&gt;
I can add: {{ 1+2 }}.
&lt;script src="angular.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h2>Manual Initialization</h2>
<p>If you need to have more control over the initialization process, you can use a manual
bootstrapping method instead. Examples of when you'd need to do this include using script loaders
or the need to perform an operation before Angular compiles a page.</p>
<p>Here is an example of manually initializing Angular. The example is equivalent to using the <a href="api/ng.directive:ngApp"><code>ng-app</code></a> directive.</p>
<pre class="prettyprint linenums">
&lt;!doctype html&gt;
&lt;html xmlns:ng="http://angularjs.org"&gt;
&lt;body&gt;
Hello {{'World'}}!
&lt;script src="http://code.angularjs.org/angular.js"&gt;&lt;/script&gt;
&lt;script&gt;
angular.element(document).ready(function() {
angular.bootstrap(document);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>This is the sequence that your code should follow:</p>
<ol>
<li><p>After the page and all of the code is loaded, find the root of the HTML template, which is
typically the root of the document.</p></li>
<li><p>Call <a href="api/angular.bootstrap"><code>api/angular.bootstrap</code></a> to <a href="guide/compiler">compile</a> the template into an
executable, bi-directionally bound application.</p></li>
</ol></div>

View file

@ -0,0 +1,142 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>Overview</h2>
<p>Angular's <a href="api/ng.$compile"><code>HTML compiler</code></a> allows the developer to teach the
browser new HTML syntax. The compiler allows you to attach behavior to any HTML element or attribute
and even create new HTML element or attributes with custom behavior. Angular calls these behavior
extensions <a href="api/ng.$compileProvider#directive"><code>directives</code></a>.</p>
<p>HTML has a lot of constructs for formatting the HTML for static documents in a declarative fashion.
For example if something needs to be centered, there is no need to provide instructions to the
browser how the window size needs to be divided in half so that center is found, and that this
center needs to be aligned with the text's center. Simply add <code>align="center"</code> attribute to any
element to achieve the desired behavior. Such is the power of declarative language.</p>
<p>But the declarative language is also limited, since it does not allow you to teach the browser new
syntax. For example there is no easy way to get the browser to align the text at 1/3 the position
instead of 1/2. What is needed is a way to teach browser new HTML syntax.</p>
<p>Angular comes pre-bundled with common directives which are useful for building any app. We also
expect that you will create directives that are specific to your app. These extension become a
Domain Specific Language for building your application.</p>
<p>All of this compilation takes place in the web browser; no server side or pre-compilation step is
involved.</p>
<h2>Compiler</h2>
<p>Compiler is an angular service which traverses the DOM looking for attributes. The compilation
process happens into two phases.</p>
<ol>
<li><p><strong>Compile:</strong> traverse the DOM and collect all of the directives. The result is a linking
function.</p></li>
<li><p><strong>Link:</strong> combine the directives with a scope and produce a live view. Any changes in the
scope model are reflected in the view, and any user interactions with the view are reflected
in the scope model. This makes the scope model the single source of truth.</p></li>
</ol>
<p>Some directives such <a href="api/ng.directive:ngRepeat"><code><code>ng-repeat</code></code></a> clone DOM elements once for each item in collection. Having a compile and link phase
improves performance since the cloned template only needs to be compiled once, and then linked
once for each clone instance.</p>
<h2>Directive</h2>
<p>A directive is a behavior which should be triggered when specific HTML constructs are encountered in
the compilation process. The directives can be placed in element names, attributes, class names, as
well as comments. Here are some equivalent examples of invoking the <a href="api/ng.directive:ngBind"><code><code>ng-bind</code></code></a> directive.</p>
<pre class="prettyprint linenums">
&lt;span ng-bind="exp"&gt;&lt;/span&gt;
&lt;span class="ng-bind: exp;"&gt;&lt;/span&gt;
&lt;ng-bind&gt;&lt;/ng-bind&gt;
&lt;!-- directive: ng-bind exp --&gt;
</pre>
<p>A directive is just a function which executes when the compiler encounters it in the DOM. See <a href="api/ng.$compileProvider#directive"><code>directive API</code></a> for in-depth documentation on how
to write directives.</p>
<p>Here is a directive which makes any element draggable. Notice the <code>draggable</code> attribute on the
<code>&lt;span&gt;</code> element.</p>
<h3>Source</h3>
<div source-edit="drag" source-edit-deps="angular.js script.js" source-edit-html="index.html-16" source-edit-css="" source-edit-js="script.js-15" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-16" ng-html-wrap="drag angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-16">
<span draggable>Drag ME</span>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-15"></pre>
<script type="text/ng-template" id="script.js-15">
angular.module('drag', []).
directive('draggable', function($document) {
var startX=0, startY=0, x = 0, y = 0;
return function(scope, element, attr) {
element.css({
position: 'relative',
border: '1px solid red',
backgroundColor: 'lightgrey',
cursor: 'pointer'
});
element.bind('mousedown', function(event) {
startX = event.screenX - x;
startY = event.screenY - y;
$document.bind('mousemove', mousemove);
$document.bind('mouseup', mouseup);
});
function mousemove(event) {
y = event.screenY - startY;
x = event.screenX - startX;
element.css({
top: y + 'px',
left: x + 'px'
});
}
function mouseup() {
$document.unbind('mousemove', mousemove);
$document.unbind('mouseup', mouseup);
}
}
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="drag" ng-set-html="index.html-16" ng-eval-javascript="script.js-15"></div>
<p>The presence of the <code>draggable</code> attribute on any element gives the element new behavior. The beauty of
this approach is that we have taught the browser a new trick. We have extended the vocabulary of
what the browser understands in a way which is natural to anyone who is familiar with HTML
principles.</p>
<h2>Understanding View</h2>
<p>There are many templating systems out there. Most of them consume a static string template and
combine it with data, resulting in a new string. The resulting text is then <code>innerHTML</code>ed into
an element.</p>
<p><img src="img/One_Way_Data_Binding.png"></p>
<p>This means that any changes to the data need to be re-merged with the template and then
<code>innerHTML</code>ed into the DOM. Some of the issues with this approach are: reading user input and merging it with data,
clobbering user input by overwriting it, managing the whole update process, and lack of behavior
expressiveness.</p>
<p>Angular is different. The Angular compiler consumes the DOM with directives, not string templates.
The result is a linking function, which when combined with a scope model results in a live view. The
view and scope model bindings are transparent. No action from the developer is needed to update
the view. And because no <code>innerHTML</code> is used there are no issues of clobbering user input.
Furthermore, Angular directives can contain not just text bindings, but behavioral constructs as
well.</p>
<p><img src="img/Two_Way_Data_Binding.png"></p>
<p>The Angular approach produces a stable DOM. This means that the DOM element instance bound to a model
item instance does not change for the lifetime of the binding. This means that the code can get
hold of the elements and register event handlers and know that the reference will not be destroyed
by template data merge.</p></div>

View file

@ -0,0 +1,523 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>Overview</h2>
<p>This document gives a quick overview of the main angular components and how they work together.
These are:</p>
<ul>
<li><a href="guide/concepts#startup">startup</a> - bring up hello world</li>
<li><a href="guide/concepts#runtime">runtime</a> - overview of angular runtime</li>
<li><a href="guide/concepts#scope">scope</a> - the glue between the view and the controller</li>
<li><a href="guide/concepts#controller">controller</a> - application behavior</li>
<li><a href="guide/concepts#model">model</a> - your application data</li>
<li><a href="guide/concepts#view">view</a> - what the user sees</li>
<li><a href="guide/concepts#directives">directives</a> - extend HTML vocabulary</li>
<li><a href="guide/concepts#filters">filters</a> - format the data in user locale</li>
<li><a href="guide/concepts#injector">injector</a> - assembles your application</li>
<li><a href="guide/concepts#module">module</a> - configures the injector</li>
<li><a href="guide/concepts#angular_namespace"><code>$</code></a> - angular namespace</li>
</ul>
<p><a name="startup"></a></p>
<h2>Startup</h2>
<p>This is how we get the ball rolling (refer to the diagram and example below):</p>
<p><img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png"></p>
<ol>
<li>The browser loads the HTML and parses it into a DOM</li>
<li>The browser loads <code>angular.js</code> script</li>
<li>Angular waits for <code>DOMContentLoaded</code> event</li>
<li>Angular looks for <a href="api/ng.directive:ngApp"><code>ng-app</code></a>
<a href="guide/directive">directive</a>, which designates the application boundary</li>
<li>The <a href="guide/module">Module</a> specified in <a href="api/ng.directive:ngApp"><code>ng-app</code></a> (if any) is used to configure
the <a href="api/AUTO.$injector"><code>$injector</code></a></li>
<li>The <a href="api/AUTO.$injector"><code>$injector</code></a> is used to create the <a href="api/ng.$compile"><code>$compile</code></a> service as well as <a href="api/ng.$rootScope"><code>$rootScope</code></a></li>
<li>The <a href="api/ng.$compile"><code>$compile</code></a> service is used to compile the DOM and link
it with <a href="api/ng.$rootScope"><code>$rootScope</code></a></li>
<li>The <a href="api/ng.directive:ngInit"><code>ng-init</code></a> <a href="guide/directive">directive</a> assigns <code>World</code> to the <code>name</code> property on the <a href="guide/scope">scope</a></li>
<li>The <code>{{name}}</code> <a href="api/ng.$interpolate"><code>interpolates</code></a> the expression to
<code>Hello World!</code></li>
</ol>
<div class="clear">
</div>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-17" source-edit-css="" source-edit-js="" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-17" ng-html-wrap=" angular.js"></pre>
<script type="text/ng-template" id="index.html-17">
<p ng-init=" name='World' ">Hello {{name}}!</p>
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-17" ng-eval-javascript=""></div>
<p><a name="runtime"></a></p>
<h2>Runtime</h2>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png"></p>
<p>The diagram and the example below describe how Angular interacts with the browser's event loop.</p>
<ol>
<li>The browser's event-loop waits for an event to arrive. An event is a user interactions, timer event,
or network event (response from a server).</li>
<li>The event's callback gets executed. This enters the JavaScript context. The callback can
modify the DOM structure.</li>
<li>Once the callback executes, the browser leaves the JavaScript context and
re-renders the view based on DOM changes.</li>
</ol>
<p>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 a third-party library callbacks.</p>
<ol>
<li>Enter Angular execution context by calling <a href="guide/scope">scope</a><code>.</code><a href="api/ng.$rootScope.Scope#$apply"><code>$apply</code></a><code>(stimulusFn)</code>. Where <code>stimulusFn</code> is
the work you wish to do in Angular execution context.</li>
<li>Angular executes the <code>stimulusFn()</code>, which typically modifies application state.</li>
<li>Angular enters the <a href="api/ng.$rootScope.Scope#$digest"><code>$digest</code></a> loop. The
loop is made up of two smaller loops which process <a href="api/ng.$rootScope.Scope#$evalAsync"><code>$evalAsync</code></a> queue and the <a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a> list. The <a href="api/ng.$rootScope.Scope#$digest"><code>$digest</code></a> loop keeps iterating until the model
stabilizes, which means that the <a href="api/ng.$rootScope.Scope#$evalAsync"><code>$evalAsync</code></a> queue is empty and the <a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a> list does not detect any changes.</li>
<li>The <a href="api/ng.$rootScope.Scope#$evalAsync"><code>$evalAsync</code></a> 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 <code>setTimeout(0)</code>, but the <code>setTimeout(0)</code> approach
suffers from slowness and may cause view flickering since the browser renders the view after
each event.</li>
<li>The <a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a> list is a set of expressions
which may have changed since last iteration. If a change is detected then the <code>$watch</code>
function is called which typically updates the DOM with the new value.</li>
<li>Once the Angular <a href="api/ng.$rootScope.Scope#$digest"><code>$digest</code></a> loop finishes
the execution leaves the Angular and JavaScript context. This is followed by the browser
re-rendering the DOM to reflect any changes.</li>
</ol>
<p>Here is the explanation of how the <code>Hello wold</code> example achieves the data-binding effect when the
user enters text into the text field.</p>
<ol>
<li>During the compilation phase:
<ol><li>the <a href="api/ng.directive:ngModel"><code>ng-model</code></a> and <a href="api/ng.directive:input"><code>input</code></a> <a href="guide/directive">directive</a> set up a <code>keydown</code> listener on the <code>&lt;input&gt;</code> control.</li>
<li>the <a href="api/ng.$interpolate"><code>&#123;&#123;name&#125;&#125;</code></a> interpolation
sets up a <a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a> to be notified of
<code>name</code> changes.</li></ol></li>
<li>During the runtime phase:
<ol><li>Pressing an '<code>X</code>' key causes the browser to emit a <code>keydown</code> event on the input control.</li>
<li>The <a href="api/ng.directive:input"><code>input</code></a> directive
captures the change to the input's value and calls <a href="api/ng.$rootScope.Scope#$apply"><code>$apply</code></a><code>("name = 'X';")</code> to update the
application model inside the Angular execution context.</li>
<li>Angular applies the <code>name = 'X';</code> to the model.</li>
<li>The <a href="api/ng.$rootScope.Scope#$digest"><code>$digest</code></a> loop begins</li>
<li>The <a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a> list detects a change
on the <code>name</code> property and notifies the <a href="api/ng.$interpolate"><code>&#123;&#123;name&#125;&#125;</code></a> interpolation, which in turn updates the DOM.</li>
<li>Angular exits the execution context, which in turn exits the <code>keydown</code> event and with it
the JavaScript execution context.</li>
<li>The browser re-renders the view with update text.</li></ol></li>
</ol>
<div class="clear">
</div>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-18" source-edit-css="" source-edit-js="" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-18" ng-html-wrap=" angular.js"></pre>
<script type="text/ng-template" id="index.html-18">
<input ng-model="name">
<p>Hello {{name}}!</p>
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-18" ng-eval-javascript=""></div>
<p><a name="scope"></a></p>
<h2>Scope</h2>
<p>The <a href="guide/scope">scope</a> 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.)</p>
<p>The following example demonstrates how <code>name</code> <a href="guide/expression">expression</a> will evaluate
into different value depending on which scope it is evaluated in. The example is followed by
a diagram depicting the scope boundaries.</p>
<div class="clear">
</div>
<div class="show-scope">
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-19" source-edit-css="style.css-21" source-edit-js="script.js-20" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-19" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-19">
<div ng-controller="GreetCtrl">
Hello {{name}}!
</div>
<div ng-controller="ListCtrl">
<ol>
<li ng-repeat="name in names">{{name}}</li>
</ol>
</div>
</script>
</div>
<div class="tab-pane" title="style.css">
<pre class="prettyprint linenums" ng-set-text="style.css-21"></pre>
<style type="text/css" id="style.css-21">
.show-scope .doc-example-live.ng-scope,
.show-scope .doc-example-live .ng-scope {
border: 1px solid red;
margin: 3px;
}
</style>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-20"></pre>
<script type="text/ng-template" id="script.js-20">
function GreetCtrl($scope) {
$scope.name = 'World';
}
function ListCtrl($scope) {
$scope.names = ['Igor', 'Misko', 'Vojta'];
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-19" ng-eval-javascript="script.js-20"></div>
</div>
<p><img class="center" src="img/guide/concepts-scope.png"></p>
<p><a name="controller"></a></p>
<h2>Controller</h2>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png"></p>
<p>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.</p>
<p>The separation of the controller and the view is important because:</p>
<ul>
<li>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).</li>
<li>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.</li>
<li>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.</li>
</ul>
<div class="clear">
</div>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-22" source-edit-css="" source-edit-js="script.js-23" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-22" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-22">
<div ng-controller="MyCtrl">
Hello {{name}}!
<button ng-click="action()">
OK
</button>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-23"></pre>
<script type="text/ng-template" id="script.js-23">
function MyCtrl($scope) {
$scope.action = function() {
$scope.name = 'OK';
}
$scope.name = 'World';
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-22" ng-eval-javascript="script.js-23"></div>
<p><a name="model"></a></p>
<h2>Model</h2>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png"></p>
<p>The model is the data which is used 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 an 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.</p>
<div class="clear">
</div>
<p><a name="view"></a></p>
<h2>View</h2>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-view.png"></p>
<p>The view is what the users sees. The view begins its life as a template, it 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.</p>
<ul>
<li><strong>Others</strong> - 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 <code>.innerHTML</code>, 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.</li>
<li><strong>Angular</strong> - 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 <a href="api/ng.$compile"><code>compiler</code></a>. The compiler
looks for <a href="guide/directive">directives</a> which in turn set up <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a> 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.</li>
</ul>
<div class="clear">
</div>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-24" source-edit-css="" source-edit-js="" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-24" ng-html-wrap=" angular.js"></pre>
<script type="text/ng-template" id="index.html-24">
<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>
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-24" ng-eval-javascript=""></div>
<p><a name="directives"></a></p>
<h2>Directives</h2>
<p>A directive is a behavior or DOM transformation which is triggered by the presence of a custom attribute,
element name, or a class name. A directive allows you to extend the HTML vocabulary in a
declarative fashion. Following is an example which enables data-binding for the <code>contenteditable</code>
in HTML.</p>
<h3>Source</h3>
<div source-edit="directive" source-edit-deps="angular.js script.js" source-edit-html="index.html-26" source-edit-css="style.css-27" source-edit-js="script.js-25" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-26" ng-html-wrap="directive angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-26">
<div contentEditable="true" ng-model="content">Edit Me</div>
<pre>model = {{content}}</pre>
</script>
</div>
<div class="tab-pane" title="style.css">
<pre class="prettyprint linenums" ng-set-text="style.css-27"></pre>
<style type="text/css" id="style.css-27">
div[contentEditable] {
cursor: pointer;
background-color: #D0D0D0;
margin-bottom: 1em;
padding: 1em;
}
</style>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-25"></pre>
<script type="text/ng-template" id="script.js-25">
angular.module('directive', []).directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('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());
}
};
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="directive" ng-set-html="index.html-26" ng-eval-javascript="script.js-25"></div>
<p><a name="filters"></a></p>
<h2>Filters</h2>
<p><a href="api/ng.$filter"><code>Filters</code></a> 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 <code>|</code> (pipe).</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-28" source-edit-css="" source-edit-js="" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-28" ng-html-wrap=" angular.js"></pre>
<script type="text/ng-template" id="index.html-28">
<div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
Number formatting: {{ 1234567890 | number }} <br>
array filtering <input ng-model="predicate">
{{ list | filter:predicate | json }}
</div>
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-28" ng-eval-javascript=""></div>
<p><a name="module"></a>
<a name="injector"></a></p>
<h2>Modules and the Injector</h2>
<p><img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png"></p>
<p>The <a href="api/AUTO.$injector"><code>injector</code></a> is a service locator. There is a single
<a href="api/AUTO.$injector"><code>injector</code></a> per Angular <a href="api/ng.directive:ngApp"><code>application</code></a>. The <a href="api/AUTO.$injector"><code>injector</code></a> 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 <a href="api/AUTO.$injector"><code>injector</code></a> asks the instance factory to create a new instance.</p>
<p>A <a href="api/angular.Module"><code>module</code></a> is a way to configure the injector's instance factory, known
as a <a href="api/AUTO.$provide"><code>provider</code></a>.</p>
<div class='clear'>
</div>
<pre class="prettyprint linenums">
// 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>
<p>But the real magic of the <a href="api/AUTO.$injector"><code>injector</code></a> is that it can be
used to <a href="api/AUTO.$injector#invoke"><code>call</code></a> methods and <a href="api/AUTO.$injector#instantiate"><code>instantiate</code></a> types. This subtle feature is what
allows the methods and types to ask for their dependencies instead of having to look for them.</p>
<pre class="prettyprint linenums">
// 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>
<p>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 <a href="api/AUTO.$injector#invoke"><code>call</code></a> which will automatically fill the function
arguments.</p>
<p>Examine the <code>ClockCtrl</code> bellow, and notice how it lists the dependencies in the constructor. When the
<a href="api/ng.directive:ngController"><code>ng-controller</code></a> 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.</p>
<h3>Source</h3>
<div source-edit="timeExampleModule" source-edit-deps="angular.js script.js" source-edit-html="index.html-29" source-edit-css="" source-edit-js="script.js-30" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-29" ng-html-wrap="timeExampleModule angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-29">
<div ng-controller="ClockCtrl">
Current time is: {{ time.now }}
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-30"></pre>
<script type="text/ng-template" id="script.js-30">
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;
});
// 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;
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="timeExampleModule" ng-set-html="index.html-29" ng-eval-javascript="script.js-30"></div>
<p><a name="angular_namespace"></a></p>
<h2>Angular Namespace</h2>
<p>To prevent accidental name collision, Angular prefixes names of objects which could potentially
collide with <code>$</code>. Please do not use the <code>$</code> prefix in your code as it may accidentally collide
with Angular code.</p></div>

View file

@ -0,0 +1,211 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>As applications grow in size and complexity, it becomes unrealistic to rely on manual testing to
verify the correctness of new features, catch bugs and notice regressions.</p>
<p>To solve this problem, we have built an Angular Scenario Runner which simulates user interactions
that will help you verify the health of your Angular application.</p>
<h2>Overview</h2>
<p>You will write scenario tests in JavaScript, which describe how your application should behave,
given a certain interaction in a specific state. A scenario is comprised of one or more <code>it</code> blocks
(you can think of these as the requirements of your application), which in turn are made of
<strong>commands</strong> and <strong>expectations</strong>. Commands tell the Runner to do something with the application
(such as navigate to a page or click on a button), and expectations tell the Runner to assert
something about the state (such as the value of a field or the current URL). If any expectation
fails, the runner marks the <code>it</code> as "failed" and continues on to the next one. Scenarios may also
have <strong>beforeEach</strong> and <strong>afterEach</strong> blocks, which will be run before (or after) each <code>it</code> block,
regardless of whether they pass or fail.</p>
<p><img src="img/guide/scenario_runner.png"></p>
<p>In addition to the above elements, scenarios may also contain helper functions to avoid duplicating
code in the <code>it</code> blocks.</p>
<p>Here is an example of a simple scenario:
<pre class="prettyprint linenums">
describe('Buzz Client', function() {
it('should filter results', function() {
input('user').enter('jacksparrow');
element(':button').click();
expect(repeater('ul li').count()).toEqual(10);
input('filterText').enter('Bees');
expect(repeater('ul li').count()).toEqual(1);
});
});
</pre>
This scenario describes the requirements of a Buzz Client, specifically, that it should be able to
filter the stream of the user. It starts by entering a value in the 'user' input field, clicking
the only button on the page, and then it verifies that there are 10 items listed. It then enters
'Bees' in the 'filterText' input field and verifies that the list is reduced to a single item.</p>
<p>The API section below lists the available commands and expectations for the Runner.</p>
<h2>API</h2>
<p>Source: <a href="https://github.com/angular/angular.js/blob/master/src/ngScenario/dsl.js">https://github.com/angular/angular.js/blob/master/src/ngScenario/dsl.js</a></p>
<h3>pause()</h3>
<p>Pauses the execution of the tests until you call <code>resume()</code> in the console (or click the resume
link in the Runner UI).</p>
<h3>sleep(seconds)</h3>
<p>Pauses the execution of the tests for the specified number of <code>seconds</code>.</p>
<h3>browser().navigateTo(url)</h3>
<p>Loads the <code>url</code> into the test frame.</p>
<h3>browser().navigateTo(url, fn)</h3>
<p>Loads the URL returned by <code>fn</code> into the testing frame. The given <code>url</code> is only used for the test
output. Use this when the destination URL is dynamic (that is, the destination is unknown when you
write the test).</p>
<h3>browser().reload()</h3>
<p>Refreshes the currently loaded page in the test frame.</p>
<h3>browser().window().href()</h3>
<p>Returns the window.location.href of the currently loaded page in the test frame.</p>
<h3>browser().window().path()</h3>
<p>Returns the window.location.pathname of the currently loaded page in the test frame.</p>
<h3>browser().window().search()</h3>
<p>Returns the window.location.search of the currently loaded page in the test frame.</p>
<h3>browser().window().hash()</h3>
<p>Returns the window.location.hash (without <code>#</code>) of the currently loaded page in the test frame.</p>
<h3>browser().location().url()</h3>
<p>Returns the <a href="api/ng.$location"><code>$location.url()</code></a> of the currently loaded page in
the test frame.</p>
<h3>browser().location().path()</h3>
<p>Returns the <a href="api/ng.$location"><code>$location.path()</code></a> of the currently loaded page in
the test frame.</p>
<h3>browser().location().search()</h3>
<p>Returns the <a href="api/ng.$location"><code>$location.search()</code></a> of the currently loaded page
in the test frame.</p>
<h3>browser().location().hash()</h3>
<p>Returns the <a href="api/ng.$location"><code>$location.hash()</code></a> of the currently loaded page in
the test frame.</p>
<h3>expect(future).{matcher}</h3>
<p>Asserts the value of the given <code>future</code> satisfies the <code>matcher</code>. All API statements return a
<code>future</code> object, which get a <code>value</code> assigned after they are executed. Matchers are defined using
<code>angular.scenario.matcher</code>, and they use the value of futures to run the expectation. For example:
<code>expect(browser().location().href()).toEqual('http://www.google.com')</code></p>
<h3>expect(future).not().{matcher}</h3>
<p>Asserts the value of the given <code>future</code> satisfies the negation of the <code>matcher</code>.</p>
<h3>using(selector, label)</h3>
<p>Scopes the next DSL element selection.</p>
<h3>binding(name)</h3>
<p>Returns the value of the first binding matching the given <code>name</code>.</p>
<h3>input(name).enter(value)</h3>
<p>Enters the given <code>value</code> in the text field with the given <code>name</code>.</p>
<h3>input(name).check()</h3>
<p>Checks/unchecks the checkbox with the given <code>name</code>.</p>
<h3>input(name).select(value)</h3>
<p>Selects the given <code>value</code> in the radio button with the given <code>name</code>.</p>
<h3>input(name).val()</h3>
<p>Returns the current value of an input field with the given <code>name</code>.</p>
<h3>repeater(selector, label).count()</h3>
<p>Returns the number of rows in the repeater matching the given jQuery <code>selector</code>. The <code>label</code> is
used for test output.</p>
<h3>repeater(selector, label).row(index)</h3>
<p>Returns an array with the bindings in the row at the given <code>index</code> in the repeater matching the
given jQuery <code>selector</code>. The <code>label</code> is used for test output.</p>
<h3>repeater(selector, label).column(binding)</h3>
<p>Returns an array with the values in the column with the given <code>binding</code> in the repeater matching
the given jQuery <code>selector</code>. The <code>label</code> is used for test output.</p>
<h3>select(name).option(value)</h3>
<p>Picks the option with the given <code>value</code> on the select with the given <code>name</code>.</p>
<h3>select(name).option(value1, value2...)</h3>
<p>Picks the options with the given <code>values</code> on the multi select with the given <code>name</code>.</p>
<h3>element(selector, label).count()</h3>
<p>Returns the number of elements that match the given jQuery <code>selector</code>. The <code>label</code> is used for test
output.</p>
<h3>element(selector, label).click()</h3>
<p>Clicks on the element matching the given jQuery <code>selector</code>. The <code>label</code> is used for test output.</p>
<h3>element(selector, label).query(fn)</h3>
<p>Executes the function <code>fn(selectedElements, done)</code>, where selectedElements are the elements that
match the given jQuery <code>selector</code> and <code>done</code> is a function that is called at the end of the <code>fn</code>
function. The <code>label</code> is used for test output.</p>
<h3>element(selector, label).{method}()</h3>
<p>Returns the result of calling <code>method</code> on the element matching the given jQuery <code>selector</code>, where
<code>method</code> can be any of the following jQuery methods: <code>val</code>, <code>text</code>, <code>html</code>, <code>height</code>,
<code>innerHeight</code>, <code>outerHeight</code>, <code>width</code>, <code>innerWidth</code>, <code>outerWidth</code>, <code>position</code>, <code>scrollLeft</code>,
<code>scrollTop</code>, <code>offset</code>. The <code>label</code> is used for test output.</p>
<h3>element(selector, label).{method}(value)</h3>
<p>Executes the <code>method</code> passing in <code>value</code> on the element matching the given jQuery <code>selector</code>, where
<code>method</code> can be any of the following jQuery methods: <code>val</code>, <code>text</code>, <code>html</code>, <code>height</code>,
<code>innerHeight</code>, <code>outerHeight</code>, <code>width</code>, <code>innerWidth</code>, <code>outerWidth</code>, <code>position</code>, <code>scrollLeft</code>,
<code>scrollTop</code>, <code>offset</code>. The <code>label</code> is used for test output.</p>
<h3>element(selector, label).{method}(key)</h3>
<p>Returns the result of calling <code>method</code> passing in <code>key</code> on the element matching the given jQuery
<code>selector</code>, where <code>method</code> can be any of the following jQuery methods: <code>attr</code>, <code>prop</code>, <code>css</code>. The
<code>label</code> is used for test output.</p>
<h3>element(selector, label).{method}(key, value)</h3>
<p>Executes the <code>method</code> passing in <code>key</code> and <code>value</code> on the element matching the given jQuery
<code>selector</code>, where <code>method</code> can be any of the following jQuery methods: <code>attr</code>, <code>prop</code>, <code>css</code>. The
<code>label</code> is used for test output.</p>
<p>JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
angular which makes testing your angular applications easy. So there is no excuse for not testing.</p></div>

View file

@ -0,0 +1,25 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>While Model-View-Controller (MVC) has acquired different shades of meaning over the years since it
first appeared, Angular incorporates the basic principles behind the original <a href="http://en.wikipedia.org/wiki/Modelviewcontroller">MVC</a> software design pattern into its way of
building client-side web applications.</p>
<p>The MVC pattern summarized:</p>
<ul>
<li>Separate applications into distinct presentation, data, and logic components</li>
<li>Encourage loose coupling between these components</li>
</ul>
<p>Along with <a href="guide/dev_guide.services">services</a> and <a href="guide/di">dependency injection</a>, MVC
makes angular applications better structured, easier to maintain and more testable.</p>
<p>The following topics explain how angular incorporates the MVC pattern into the angular way of
developing web applications:</p>
<ul>
<li><a href="guide/dev_guide.mvc.understanding_model">Understanding the Model Component</a></li>
<li><a href="guide/dev_guide.mvc.understanding_controller">Understanding the Controller Component</a></li>
<li><a href="guide/dev_guide.mvc.understanding_view">Understanding the View Component</a></li>
</ul></div>

View file

@ -0,0 +1,289 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>In Angular, a controller is a JavaScript function(type/class) that is used to augment instances of
angular <a href="guide/scope">Scope</a>, excluding the root scope. When you or Angular create a new
child scope object via the <a href="api/ng.$rootScope.Scope#$new"><code>scope.$new</code></a> API , there is an
option to pass in a controller as a method argument. This will tell Angular to associate the
controller with the new scope and to augment its behavior.</p>
<p>Use controllers to:</p>
<ul>
<li>Set up the initial state of a scope object.</li>
<li>Add behavior to the scope object.</li>
</ul>
<h2>Setting up the initial state of a scope object</h2>
<p>Typically, when you create an application you need to set up an initial state for an Angular scope.</p>
<p>Angular applies (in the sense of JavaScript's <code>Function#apply</code>) the controller constructor function
to a new Angular scope object, which sets up an initial scope state. This means that Angular never
creates instances of the controller type (by invoking the <code>new</code> operator on the controller
constructor). Constructors are always applied to an existing scope object.</p>
<p>You set up the initial state of a scope by creating model properties. For example:</p>
<p>function GreetingCtrl($scope) {
$scope.greeting = 'Hola!';
}</p>
<p>The <code>GreetingCtrl</code> controller creates a <code>greeting</code> model which can be referred to in a template.</p>
<p><strong>NOTE</strong>: Many of the examples in the documentation show the creation of functions
in the global scope. This is only for demonstration purposes - in a real
application you should use the <code>.controller</code> method of your Angular module for
your application as follows:</p>
<p>var myApp = angular.module('myApp',[]);</p>
<p>myApp.controller('GreetingCtrl', ['$scope', function(scope) {
scope.greeting = 'Hola!';
}]);</p>
<p>Note also that we use the array notation to explicitly specify the dependency
of the controller on the <code>$scope</code> service provided by Angular.</p>
<h2>Adding Behavior to a Scope Object</h2>
<p>Behavior on an Angular scope object is in the form of scope method properties available to the
template/view. This behavior interacts with and modifies the application model.</p>
<p>As discussed in the <a href="guide/dev_guide.mvc.understanding_model">Model</a> section of this guide, any
objects (or primitives) assigned to the scope become model properties. Any functions assigned to
the scope are available in the template/view, and can be invoked via angular expressions
and <code>ng</code> event handler directives (e.g. <a href="api/ng.directive:ngClick"><code>ngClick</code></a>).</p>
<h2>Using Controllers Correctly</h2>
<p>In general, a controller shouldn't try to do too much. It should contain only the business logic
needed for a single view.</p>
<p>The most common way to keep controllers slim is by encapsulating work that doesn't belong to
controllers into services and then using these services in controllers via dependency injection.
This is discussed in the <a href="guide/di">Dependency Injection</a> <a href="guide/dev_guide.services">Services</a> sections of this guide.</p>
<p>Do not use controllers for:</p>
<ul>
<li>Any kind of DOM manipulation — Controllers should contain only business logic. DOM
manipulation—the presentation logic of an application—is well known for being hard to test.
Putting any presentation logic into controllers significantly affects testability of the business
logic. Angular offers <a href="guide/dev_guide.templates.databinding">databinding</a> for automatic DOM manipulation. If
you have to perform your own manual DOM manipulation, encapsulate the presentation logic in
<a href="guide/directive">directives</a>.</li>
<li>Input formatting — Use <a href="guide/forms">angular form controls</a> instead.</li>
<li>Output filtering — Use <a href="guide/dev_guide.templates.filters">angular filters</a> instead.</li>
<li>To run stateless or stateful code shared across controllers — Use <a href="guide/dev_guide.services">angular services</a> instead.</li>
<li>To instantiate or manage the life-cycle of other components (for example, to create service
instances).</li>
</ul>
<h2>Associating Controllers with Angular Scope Objects</h2>
<p>You can associate controllers with scope objects explicitly via the <a href="api/ng.$rootScope.Scope#$new"><code>scope.$new</code></a> api or implicitly via the <a href="api/ng.directive:ngController"><code>ngController directive</code></a> or <a href="api/ng.$route"><code>$route service</code></a>.</p>
<h3>Controller Constructor and Methods Example</h3>
<p>To illustrate how the controller component works in angular, let's create a little app with the
following components:</p>
<ul>
<li>A <a href="guide/dev_guide.templates">template</a> with two buttons and a simple message</li>
<li>A model consisting of a string named <code>spice</code></li>
<li>A controller with two functions that set the value of <code>spice</code></li>
</ul>
<p>The message in our template contains a binding to the <code>spice</code> model, which by default is set to the
string "very". Depending on which button is clicked, the <code>spice</code> model is set to <code>chili</code> or
<code>jalapeño</code>, and the message is automatically updated by data-binding.</p>
<h3>A Spicy Controller Example</h3>
<pre class="prettyprint linenums">
&lt;body ng-controller="SpicyCtrl"&gt;
&lt;button ng-click="chiliSpicy()"&gt;Chili&lt;/button&gt;
&lt;button ng-click="jalapenoSpicy()"&gt;Jalapeño&lt;/button&gt;
&lt;p&gt;The food is {{spice}} spicy!&lt;/p&gt;
&lt;/body&gt;
function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.chiliSpicy = function() {
$scope.spice = 'chili';
}
$scope.jalapenoSpicy = function() {
$scope.spice = 'jalapeño';
}
}
</pre>
<p>Things to notice in the example above:</p>
<ul>
<li>The <code>ngController</code> directive is used to (implicitly) create a scope for our template, and the
scope is augmented (managed) by the <code>SpicyCtrl</code> controller.</li>
<li><code>SpicyCtrl</code> is just a plain JavaScript function. As an (optional) naming convention the name
starts with capital letter and ends with "Ctrl" or "Controller".</li>
<li>Assigning a property to <code>$scope</code> creates or updates the model.</li>
<li>Controller methods can be created through direct assignment to scope (the <code>chiliSpicy</code> method)</li>
<li>Both controller methods are available in the template (for the <code>body</code> element and and its
children).</li>
<li>NB: Previous versions of Angular (pre 1.0 RC) allowed you to use <code>this</code> interchangeably with
the $scope method, but this is no longer the case. Inside of methods defined on the scope
<code>this</code> and $scope are interchangeable (angular sets <code>this</code> to $scope), but not otherwise
inside your controller constructor.</li>
<li>NB: Previous versions of Angular (pre 1.0 RC) added prototype methods into the scope
automatically, but this is no longer the case; all methods need to be added manually to
the scope.</li>
</ul>
<p>Controller methods can also take arguments, as demonstrated in the following variation of the
previous example.</p>
<h3>Controller Method Arguments Example</h3>
<pre class="prettyprint linenums">
&lt;body ng-controller="SpicyCtrl"&gt;
&lt;input ng-model="customSpice" value="wasabi"&gt;
&lt;button ng-click="spicy('chili')"&gt;Chili&lt;/button&gt;
&lt;button ng-click="spicy(customSpice)"&gt;Custom spice&lt;/button&gt;
&lt;p&gt;The food is {{spice}} spicy!&lt;/p&gt;
&lt;/body&gt;
function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.spicy = function(spice) {
$scope.spice = spice;
}
}
</pre>
<p>Notice that the <code>SpicyCtrl</code> controller now defines just one method called <code>spicy</code>, which takes one
argument called <code>spice</code>. The template then refers to this controller method and passes in a string
constant <code>'chili'</code> in the binding for the first button and a model property <code>spice</code> (bound to an
input box) in the second button.</p>
<h3>Controller Inheritance Example</h3>
<p>Controller inheritance in Angular is based on <a href="api/ng.$rootScope.Scope"><code>Scope</code></a> inheritance. Let's
have a look at an example:</p>
<pre class="prettyprint linenums">
&lt;body ng-controller="MainCtrl"&gt;
&lt;p&gt;Good {{timeOfDay}}, {{name}}!&lt;/p&gt;
&lt;div ng-controller="ChildCtrl"&gt;
&lt;p&gt;Good {{timeOfDay}}, {{name}}!&lt;/p&gt;
&lt;p ng-controller="BabyCtrl"&gt;Good {{timeOfDay}}, {{name}}!&lt;/p&gt;
&lt;/body&gt;
function MainCtrl($scope) {
$scope.timeOfDay = 'morning';
$scope.name = 'Nikki';
}
function ChildCtrl($scope) {
$scope.name = 'Mattie';
}
function BabyCtrl($scope) {
$scope.timeOfDay = 'evening';
$scope.name = 'Gingerbreak Baby';
}
</pre>
<p>Notice how we nested three <code>ngController</code> directives in our template. This template construct will
result in 4 scopes being created for our view:</p>
<ul>
<li>The root scope</li>
<li>The <code>MainCtrl</code> scope, which contains <code>timeOfDay</code> and <code>name</code> models</li>
<li>The <code>ChildCtrl</code> scope, which shadows the <code>name</code> model from the previous scope and inherits the
<code>timeOfDay</code> model</li>
<li>The <code>BabyCtrl</code> scope, which shadows both the <code>timeOfDay</code> model defined in <code>MainCtrl</code> and <code>name</code>
model defined in the ChildCtrl</li>
</ul>
<p>Inheritance works between controllers in the same way as it does with models. So in our previous
examples, all of the models could be replaced with controller methods that return string values.</p>
<p>Note: Standard prototypical inheritance between two controllers doesn't work as one might expect,
because as we mentioned earlier, controllers are not instantiated directly by Angular, but rather
are applied to the scope object.</p>
<h3>Testing Controllers</h3>
<p>Although there are many ways to test a controller, one of the best conventions, shown below,
involves injecting the <code>$rootScope</code> and <code>$controller</code></p>
<p>Controller Function:
<pre class="prettyprint linenums">
function myController($scope) {
$scope.spices = [{"name":"pasilla", "spiciness":"mild"},
{"name":"jalapeno", "spiceiness":"hot hot hot!"},
{"name":"habanero", "spiceness":"LAVA HOT!!"}];
$scope.spice = "habanero";
}
</pre>
<p>Controller Test:
<pre class="prettyprint linenums">
describe('myController function', function() {
describe('myController', function() {
var scope;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
var ctrl = $controller(myController, {$scope: scope});
}));
it('should create "spices" model with 3 spices', function() {
expect(scope.spices.length).toBe(3);
});
it('should set the default value of spice', function() {
expect(scope.spice).toBe('habanero');
});
});
});
</pre>
<p>If you need to test a nested controller you need to create the same scope hierarchy
in your test that exists in the DOM.</p>
<pre class="prettyprint linenums">
describe('state', function() {
var mainScope, childScope, babyScope;
beforeEach(inject(function($rootScope, $controller) {
mainScope = $rootScope.$new();
var mainCtrl = $controller(MainCtrl, {$scope: mainScope});
childScope = mainScope.$new();
var childCtrl = $controller(ChildCtrl, {$scope: childScope});
babyScope = childCtrl.$new();
var babyCtrl = $controller(BabyCtrl, {$scope: babyScope});
}));
it('should have over and selected', function() {
expect(mainScope.timeOfDay).toBe('morning');
expect(mainScope.name).toBe('Nikki');
expect(childScope.timeOfDay).toBe('morning');
expect(childScope.name).toBe('Mattie');
expect(babyScope.timeOfDay).toBe('evening');
expect(babyScope.name).toBe('Gingerbreak Baby');
});
});
</pre>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.mvc">About MVC in Angular</a></li>
<li><a href="guide/dev_guide.mvc.understanding_model">Understanding the Model Component</a></li>
<li><a href="guide/dev_guide.mvc.understanding_view">Understanding the View Component</a></li>
</ul></div>

View file

@ -0,0 +1,77 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Depending on the context of the discussion in the Angular documentation, the term <em>model</em> can refer to
either a single object representing one entity (for example, a model called "phones" with its value
being an array of phones) or the entire data model for the application (all entities).</p>
<p>In Angular, a model is any data that is reachable as a property of an angular <a href="guide/scope">Scope</a> object. The name of the property is the model identifier and the value is
any JavaScript object (including arrays and primitives).</p>
<p>The only requirement for a JavaScript object to be a model in Angular is that the object must be
referenced by an Angular scope as a property of that scope object. This property reference can be
created explicitly or implicitly.</p>
<p>You can create models by explicitly creating scope properties referencing JavaScript objects in the
following ways:</p>
<ul>
<li><p>Make a direct property assignment to the scope object in JavaScript code; this most commonly
occurs in controllers:</p>
<pre><code> function MyCtrl($scope) {
// create property 'foo' on the MyCtrl's scope
// and assign it an initial value 'bar'
$scope.foo = 'bar';
}
</code></pre></li>
<li><p>Use an <a href="guide/expression">angular expression</a> with an assignment operator in templates:</p>
<pre><code> &lt;button ng-click="{{foos='ball'}}"&gt;Click me&lt;/button&gt;
</code></pre></li>
<li><p>Use <a href="api/ng.directive:ngInit"><code>ngInit directive</code></a> in templates (for toy/example apps
only, not recommended for real applications):</p>
<pre><code> &lt;body ng-init=" foo = 'bar' "&gt;
</code></pre></li>
</ul>
<p>Angular creates models implicitly (by creating a scope property and assigning it a suitable value)
when processing the following template constructs:</p>
<ul>
<li><p>Form input, select, textarea and other form elements:</p>
<pre><code> &lt;input ng-model="query" value="fluffy cloud"&gt;
</code></pre>
<p>The code above creates a model called "query" on the current scope with the value set to "fluffy
cloud".</p></li>
<li><p>An iterator declaration in <a href="api/ng.directive:ngRepeat"><code>ngRepeater</code></a>:</p>
<pre><code> &lt;p ng-repeat="phone in phones"&gt;&lt;/p&gt;
</code></pre>
<p>The code above creates one child scope for each item in the "phones" array and creates a "phone"
object (model) on each of these scopes with its value set to the value of "phone" in the array.</p></li>
</ul>
<p>In Angular, a JavaScript object stops being a model when:</p>
<ul>
<li><p>No Angular scope contains a property that references the object.</p></li>
<li><p>All Angular scopes that contain a property referencing the object become stale and eligible for
garbage collection.</p></li>
</ul>
<p>The following illustration shows a simple data model created implicitly from a simple template:</p>
<p><img src="img/guide/about_model_final.png"></p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.mvc">About MVC in Angular</a></li>
<li><a href="guide/dev_guide.mvc.understanding_controller">Understanding the Controller Component</a></li>
<li><a href="guide/dev_guide.mvc.understanding_view">Understanding the View Component</a></li>
</ul></div>

View file

@ -0,0 +1,21 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>In Angular, the view is the DOM loaded and rendered in the browser, after Angular has transformed
the DOM based on information in the template, controller and model.</p>
<p><img src="img/guide/about_view_final.png"></p>
<p>In the Angular implementation of MVC, the view has knowledge of both the model and the controller.
The view knows about the model where two-way data-binding occurs. The view has knowledge of the
controller through Angular directives, such as <a href="api/ng.directive:ngController"><code>ngController</code></a> and <a href="api/ng.directive:ngView"><code>ngView</code></a>, and through bindings of this form:
<code>{{someControllerFunction()}}</code>. In these ways, the view can call functions in an associated
controller function.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.mvc">About MVC in Angular</a></li>
<li><a href="guide/dev_guide.mvc.understanding_model">Understanding the Model Component</a></li>
<li><a href="guide/dev_guide.mvc.understanding_controller">Understanding the Controller Component</a></li>
</ul></div>

View file

@ -0,0 +1,652 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>What does it do?</h2>
<p>The <code>$location</code> service parses the URL in the browser address bar (based on the <a href="https://developer.mozilla.org/en/window.location">window.location</a>) and makes the URL available to
your application. Changes to the URL in the address bar are reflected into $location service and
changes to $location are reflected into the browser address bar.</p>
<p><strong>The $location service:</strong></p>
<ul>
<li>Exposes the current URL in the browser address bar, so you can
<ul><li>Watch and observe the URL.</li>
<li>Change the URL.</li></ul></li>
<li>Synchronizes the URL with the browser when the user
<ul><li>Changes the address bar.</li>
<li>Clicks the back or forward button (or clicks a History link).</li>
<li>Clicks on a link.</li></ul></li>
<li>Represents the URL object as a set of methods (protocol, host, port, path, search, hash).</li>
</ul>
<h3>Comparing $location to window.location</h3>
<table class="table">
<thead>
<tr>
<th class="empty-corner-lt"></th>
<th>window.location</th>
<th>$location service</th>
</tr>
</thead>
<tbody>
<tr>
<td class="head">purpose</td>
<td>allow read/write access to the current browser location</td>
<td>same</td>
</tr>
<tr>
<td class="head">API</td>
<td>exposes "raw" object with properties that can be directly modified</td>
<td>exposes jQuery-style getters and setters</td>
</tr>
<tr>
<td class="head">integration with angular application life-cycle</td>
<td>none</td>
<td>knows about all internal life-cycle phases, integrates with $watch, ...</td>
</tr>
<tr>
<td class="head">seamless integration with HTML5 API</td>
<td>no</td>
<td>yes (with a fallback for legacy browsers)</td>
</tr>
<tr>
<td class="head">aware of docroot/context from which the application is loaded</td>
<td>no - window.location.path returns "/docroot/actual/path"</td>
<td>yes - $location.path() returns "/actual/path"</td>
</tr>
</tbody>
</table>
<h3>When should I use $location?</h3>
<p>Any time your application needs to react to a change in the current URL or if you want to change
the current URL in the browser.</p>
<h3>What does it not do?</h3>
<p>It does not cause a full page reload when the browser URL is changed. To reload the page after
changing the URL, use the lower-level API, <code>$window.location.href</code>.</p>
<h2>General overview of the API</h2>
<p>The <code>$location</code> service can behave differently, depending on the configuration that was provided to
it when it was instantiated. The default configuration is suitable for many applications, for
others customizing the configuration can enable new features.</p>
<p>Once the <code>$location</code> service is instantiated, you can interact with it via jQuery-style getter and
setter methods that allow you to get or change the current URL in the browser.</p>
<h3>$location service configuration</h3>
<p>To configure the <code>$location</code> service, retrieve the
<a href="api/ng.$locationProvider"><code>$locationProvider</code></a> and set the parameters as follows:</p>
<ul>
<li><p><strong>html5Mode(mode)</strong>: {boolean}<br />
<code>true</code> - see HTML5 mode<br />
<code>false</code> - see Hashbang mode<br />
default: <code>false</code></p></li>
<li><p><strong>hashPrefix(prefix)</strong>: {string}<br />
prefix used for Hashbang URLs (used in Hashbang mode or in legacy browser in Html5 mode)<br />
default: <code>'!'</code></p></li>
</ul>
<h4>Example configuration</h4>
<pre class="prettyprint linenums">
$locationProvider.html5Mode(true).hashPrefix('!');
</pre>
<h3>Getter and setter methods</h3>
<p><code>$location</code> service provides getter methods for read-only parts of the URL (absUrl, protocol, host,
port) and getter / setter methods for url, path, search, hash:
<pre class="prettyprint linenums">
// get the current path
$location.path();
// change the path
$location.path('/newValue')
</pre>
<p>All of the setter methods return the same <code>$location</code> object to allow chaining. For example, to
change multiple segments in one go, chain setters like this:
<pre class="prettyprint linenums">$location.path('/newValue').search({key: value});</pre>
<p>There is a special <code>replace</code> method which can be used to tell the $location service that the next
time the $location service is synced with the browser, the last history record should be replaced
instead of creating a new one. This is useful when you want to implement redirection, which would
otherwise break the back button (navigating back would retrigger the redirection). To change the
current URL without creating a new browser history record you can call:
<pre class="prettyprint linenums">
$location.path('/someNewPath');
$location.replace();
// or you can chain these as: $location.path('/someNewPath').replace();
</pre>
<p>Note that the setters don't update <code>window.location</code> immediately. Instead, the <code>$location</code> service is
aware of the <a href="api/ng.$rootScope.Scope"><code>scope</code></a> life-cycle and coalesces multiple <code>$location</code>
mutations into one "commit" to the <code>window.location</code> object during the scope <code>$digest</code> phase. Since
multiple changes to the $location's state will be pushed to the browser as a single change, it's
enough to call the <code>replace()</code> method just once to make the entire "commit" a replace operation
rather than an addition to the browser history. Once the browser is updated, the $location service
resets the flag set by <code>replace()</code> method and future mutations will create new history records,
unless <code>replace()</code> is called again.</p>
<h4>Setters and character encoding</h4>
<p>You can pass special characters to <code>$location</code> service and it will encode them according to rules
specified in <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>. When you access the methods:</p>
<ul>
<li>All values that are passed to <code>$location</code> setter methods, <code>path()</code>, <code>search()</code>, <code>hash()</code>, are
encoded.</li>
<li>Getters (calls to methods without parameters) return decoded values for the following methods
<code>path()</code>, <code>search()</code>, <code>hash()</code>.</li>
<li>When you call the <code>absUrl()</code> method, the returned value is a full url with its segments encoded.</li>
<li>When you call the <code>url()</code> method, the returned value is path, search and hash, in the form
<code>/path?search=a&amp;b=c#hash</code>. The segments are encoded as well.</li>
</ul>
<h2>Hashbang and HTML5 Modes</h2>
<p><code>$location</code> service has two configuration modes which control the format of the URL in the browser
address bar: <strong>Hashbang mode</strong> (the default) and the <strong>HTML5 mode</strong> which is based on using the
HTML5 <a href="http://www.w3.org/TR/html5/history.html">History API</a>. Applications use the same API in
both modes and the <code>$location</code> service will work with appropriate URL segments and browser APIs to
facilitate the browser URL change and history management.</p>
<p><img src="img/guide/hashbang_vs_regular_url.jpg"></p>
<table class="table">
<thead>
<tr>
<th class="empty-corner-lt"></th>
<th>Hashbang mode</th>
<th>HTML5 mode</th>
</tr>
</thead>
<tbody>
<tr>
<td class="head">configuration</td>
<td>the default</td>
<td>{ html5Mode: true }</td>
</tr>
<tr>
<td class="head">URL format</td>
<td>hashbang URLs in all browsers</td>
<td>regular URLs in modern browser, hashbang URLs in old browser</td>
</tr>
<tr>
<td class="head">&lt;a href=""&gt; link rewriting</td>
<td>no</td>
<td>yes</td>
</tr>
<tr>
<td class="head">requires server-side configuration</td>
<td>no</td>
<td>yes</td>
</tr>
</tbody>
</table>
<h3>Hashbang mode (default mode)</h3>
<p>In this mode, <code>$location</code> uses Hashbang URLs in all browsers.</p>
<h4>Example</h4>
<pre class="prettyprint linenums">
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix = '!';
},
function($location) {
// open http://host.com/base/index.html#!/a
$location.absUrl() == 'http://host.com/base/index.html#!/a'
$location.path() == '/a'
$location.path('/foo')
$location.absUrl() == 'http://host.com/base/index.html#!/foo'
$location.search() == {}
$location.search({a: 'b', c: true});
$location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
$location.path('/new').search('x=y');
$location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
}
));
</pre>
<h4>Crawling your app</h4>
<p>To allow indexing of your AJAX application, you have to add special meta tag in the head section of
your document:
<pre class="prettyprint linenums">&lt;meta name="fragment" content="!" /&gt;</pre>
<p>This will cause crawler bot to request links with <code>_escaped_fragment_</code> param so that your server
can recognize the crawler and serve a HTML snapshots. For more information about this technique,
see <a href="http://code.google.com/web/ajaxcrawling/docs/specification.html">Making AJAX Applications Crawlable</a>.</p>
<h3>HTML5 mode</h3>
<p>In HTML5 mode, the <code>$location</code> service getters and setters interact with the browser URL address
through the HTML5 history API, which allows for use of regular URL path and search segments,
instead of their hashbang equivalents. If the HTML5 History API is not supported by a browser, the
<code>$location</code> service will fall back to using the hashbang URLs automatically. This frees you from
having to worry about whether the browser displaying your app supports the history API or not; the
<code>$location</code> service transparently uses the best available option.</p>
<ul>
<li>Opening a regular URL in a legacy browser -> redirects to a hashbang URL</li>
<li>Opening hashbang URL in a modern browser -> rewrites to a regular URL</li>
</ul>
<h4>Example</h4>
<pre class="prettyprint linenums">
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix = '!';
},
function($location) {
// in browser with HTML5 history support:
// open http://host.com/#!/a -&gt; rewrite to http://host.com/a
// (replacing the http://host.com/#!/a history record)
$location.path() == '/a'
$location.path('/foo');
$location.absUrl() == 'http://host.com/foo'
$location.search() == {}
$location.search({a: 'b', c: true});
$location.absUrl() == 'http://host.com/foo?a=b&c'
$location.path('/new').search('x=y');
$location.url() == 'new?x=y'
$location.absUrl() == 'http://host.com/new?x=y'
// in browser without html5 history support:
// open http://host.com/new?x=y -&gt; redirect to http://host.com/#!/new?x=y
// (again replacing the http://host.com/new?x=y history item)
$location.path() == '/new'
$location.search() == {x: 'y'}
$location.path('/foo/bar');
$location.path() == '/foo/bar'
$location.url() == '/foo/bar?x=y'
$location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
}
));
</pre>
<h4>Fallback for legacy browsers</h4>
<p>For browsers that support the HTML5 history API, <code>$location</code> uses the HTML5 history API to write
path and search. If the history API is not supported by a browser, <code>$location</code> supplies a Hasbang
URL. This frees you from having to worry about whether the browser viewing your app supports the
history API or not; the <code>$location</code> service makes this transparent to you.</p>
<h4>Html link rewriting</h4>
<p>When you use HTML5 history API mode, you will need different links in different browsers, but all you
have to do is specify regular URL links, such as: <code>&lt;a href="/some?foo=bar"&gt;link&lt;/a&gt;</code></p>
<p>When a user clicks on this link,</p>
<ul>
<li>In a legacy browser, the URL changes to <code>/index.html#!/some?foo=bar</code></li>
<li>In a modern browser, the URL changes to <code>/some?foo=bar</code></li>
</ul>
<p>In cases like the following, links are not rewritten; instead, the browser will perform a full page
reload to the original link.</p>
<ul>
<li>Links that contain <code>target</code> element<br>
Example: <code>&lt;a href="/ext/link?a=b" target="_self"&gt;link&lt;/a&gt;</code></li>
<li>Absolute links that go to a different domain<br>
Example: <code>&lt;a href="http://angularjs.org/"&gt;link&lt;/a&gt;</code></li>
<li>Links starting with '/' that lead to a different base path when base is defined<br>
Example: <code>&lt;a href="/not-my-base/link"&gt;link&lt;/a&gt;</code></li>
</ul>
<h4>Server side</h4>
<p>Using this mode requires URL rewriting on server side, basically you have to rewrite all your links
to entry point of your application (e.g. index.html)</p>
<h4>Crawling your app</h4>
<p>If you want your AJAX application to be indexed by web crawlers, you will need to add the following
meta tag to the HEAD section of your document:
<pre class="prettyprint linenums">&lt;meta name="fragment" content="!" /&gt;</pre>
<p>This statement causes a crawler to request links with an empty <code>_escaped_fragment_</code> parameter so that
your server can recognize the crawler and serve it HTML snapshots. For more information about this
technique, see <a href="http://code.google.com/web/ajaxcrawling/docs/specification.html">Making AJAX Applications Crawlable</a>.</p>
<h4>Relative links</h4>
<p>Be sure to check all relative links, images, scripts etc. You must either specify the url base in
the head of your main html file (<code>&lt;base href="/my-base"&gt;</code>) or you must use absolute urls
(starting with <code>/</code>) everywhere because relative urls will be resolved to absolute urls using the
initial absolute url of the document, which is often different from the root of the application.</p>
<p>Running Angular apps with the History API enabled from document root is strongly encouraged as it
takes care of all relative link issues.</p>
<h4>Sending links among different browsers</h4>
<p>Because of rewriting capability in HTML5 mode, your users will be able to open regular url links in
legacy browsers and hashbang links in modern browser:</p>
<ul>
<li>Modern browser will rewrite hashbang URLs to regular URLs.</li>
<li>Older browsers will redirect regular URLs to hashbang URLs.</li>
</ul>
<h4>Example</h4>
<p>Here you can see two <code>$location</code> instances, both in <strong>Html5 mode</strong>, but on different browsers, so
that you can see the differences. These <code>$location</code> services are connected to a fake browsers. Each
input represents address bar of the browser.</p>
<p>Note that when you type hashbang url into first browser (or vice versa) it doesn't rewrite /
redirect to regular / hashbang url, as this conversion happens only during parsing the initial URL
= on page reload.</p>
<p>In this examples we use <code>&lt;base href="/base/index.html" /&gt;</code>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-32" source-edit-css="" source-edit-js="script.js-31" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-32" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-32">
<div ng-non-bindable class="html5-hashbang-example">
<div id="html5-mode" ng-controller="Html5Cntl">
<h4>Browser with History API</h4>
<div ng-address-bar browser="html5"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
<div id="hashbang-mode" ng-controller="HashbangCntl">
<h4>Browser without History API</h4>
<div ng-address-bar browser="hashbang"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-31"></pre>
<script type="text/ng-template" id="script.js-31">
function FakeBrowser(initUrl, baseHref) {
this.onUrlChange = function(fn) {
this.urlChange = fn;
};
this.url = function() {
return initUrl;
};
this.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
this.baseHref = function() {
return baseHref;
};
this.notifyWhenOutstandingRequests = angular.noop;
}
var browsers = {
html5: new FakeBrowser('http://www.host.com/base/path?a=b#h', '/base/index.html'),
hashbang: new FakeBrowser('http://www.host.com/base/index.html#!/path?a=b#h', '/base/index.html')
};
function Html5Cntl($scope, $location) {
$scope.$location = $location;
}
function HashbangCntl($scope, $location) {
$scope.$location = $location;
}
function initEnv(name) {
var root = angular.element(document.getElementById(name + '-mode'));
angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){
$locationProvider.html5Mode(true).hashPrefix('!');
$provide.value('$browser', browsers[name]);
$provide.value('$document', root);
$provide.value('$sniffer', {history: name == 'html5'});
$compileProvider.directive('ngAddressBar', function() {
return function(scope, elm, attrs) {
var browser = browsers[attrs.browser],
input = angular.element('<input type="text">').val(browser.url()),
delay;
input.bind('keypress keyup keydown', function() {
if (!delay) {
delay = setTimeout(fireUrlChange, 250);
}
});
browser.url = function(url) {
return input.val(url);
};
elm.append('Address: ').append(input);
function fireUrlChange() {
delay = null;
browser.urlChange(input.val());
}
};
});
}]);
root.bind('click', function(e) {
e.stopPropagation();
});
}
initEnv('html5');
initEnv('hashbang');
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-32" ng-eval-javascript="script.js-31"></div>
<h2>Caveats</h2>
<h3>Page reload navigation</h3>
<p>The <code>$location</code> service allows you to change only the URL; it does not allow you to reload the
page. When you need to change the URL and reload the page or navigate to a different page, please
use a lower level API, <a href="api/ng.$window"><code>$window.location.href</code></a>.</p>
<h3>Using $location outside of the scope life-cycle</h3>
<p><code>$location</code> knows about Angular's <a href="api/ng.$rootScope.Scope"><code>scope</code></a> life-cycle. When a URL changes in
the browser it updates the <code>$location</code> and calls <code>$apply</code> so that all $watchers / $observers are
notified.
When you change the <code>$location</code> inside the <code>$digest</code> phase everything is ok; <code>$location</code> will
propagate this change into browser and will notify all the $watchers / $observers.
When you want to change the <code>$location</code> from outside Angular (for example, through a DOM Event or
during testing) - you must call <code>$apply</code> to propagate the changes.</p>
<h3>$location.path() and ! or / prefixes</h3>
<p>A path should always begin with forward slash (<code>/</code>); the <code>$location.path()</code> setter will add the
forward slash if it is missing.</p>
<p>Note that the <code>!</code> prefix in the hashbang mode is not part of <code>$location.path()</code>; it is actually
hashPrefix.</p>
<h2>Testing with the $location service</h2>
<p>When using <code>$location</code> service during testing, you are outside of the angular's <a href="api/ng.$rootScope.Scope"><code>scope</code></a> life-cycle. This means it's your responsibility to call <code>scope.$apply()</code>.</p>
<pre class="prettyprint linenums">
describe('serviceUnderTest', function() {
beforeEach(module(function($provide) {
$provide.factory('serviceUnderTest', function($location){
// whatever it does...
});
});
it('should...', inject(function($location, $rootScope, serviceUnderTest) {
$location.path('/new/path');
$rootScope.$apply();
// test whatever the service should do...
}));
});
</pre>
<h2>Migrating from earlier AngularJS releases</h2>
<p>In earlier releases of Angular, <code>$location</code> used <code>hashPath</code> or <code>hashSearch</code> to process path and
search methods. With this release, the <code>$location</code> service processes path and search methods and
then uses the information it obtains to compose hashbang URLs (such as
<code>http://server.com/#!/path?search=a</code>), when necessary.</p>
<h3>Changes to your code</h3>
<table class="table">
<thead>
<tr class="head">
<th>Navigation inside the app</th>
<th>Change to</th>
</tr>
</thead>
<tbody>
<tr>
<td>$location.href = value<br />$location.hash = value<br />$location.update(value)<br
/>$location.updateHash(value)</td>
<td>$location.path(path).search(search)</td>
</tr>
<tr>
<td>$location.hashPath = path</td>
<td>$location.path(path)</td>
</tr>
<tr>
<td>$location.hashSearch = search</td>
<td>$location.search(search)</td>
</tr>
<tr class="head">
<td>Navigation outside the app</td>
<td>Use lower level API</td>
</tr>
<tr>
<td>$location.href = value<br />$location.update(value)</td>
<td>$window.location.href = value</td>
</tr>
<tr>
<td>$location[protocol | host | port | path | search]</td>
<td>$window.location[protocol | host | port | path | search]</td>
</tr>
<tr class="head">
<td>Read access</td>
<td>Change to</td>
</tr>
<tr>
<td>$location.hashPath</td>
<td>$location.path()</td>
</tr>
<tr>
<td>$location.hashSearch</td>
<td>$location.search()</td>
</tr>
<tr>
<td>$location.href<br />$location.protocol<br />$location.host<br />$location.port<br
/>$location.hash</td>
<td>$location.absUrl()<br />$location.protocol()<br />$location.host()<br />$location.port()<br
/>$location.path() + $location.search()</td>
</tr>
<tr>
<td>$location.path<br />$location.search</td>
<td>$window.location.path<br />$window.location.search</td>
</tr>
</tbody>
</table>
<h3>Two-way binding to $location</h3>
<p>The Angular's compiler currently does not support two-way binding for methods (see <a href="https://github.com/angular/angular.js/issues/404">issue</a>). If you should require two-way binding
to the $location object (using <a href="api/ng.directive:input.text"><code>ngModel</code></a> directive on an input field), you will need to specify an extra model property
(e.g. <code>locationPath</code>) with two watchers which push $location updates in both directions. For
example:
<pre class="prettyprint linenums">
&lt;!-- html --&gt;
&lt;input type="text" ng-model="locationPath" /&gt;
</pre>
<pre class="prettyprint linenums">
// js - controller
$scope.$watch('locationPath', function(path) {
$location.path(path);
});
$scope.$watch('$location.path()', function(path) {
scope.locationPath = path;
});
</pre>
<h2>Related API</h2>
<ul>
<li><a href="api/ng.$location"><code>$location API</code></a></li>
</ul></div>

View file

@ -0,0 +1,101 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>While Angular offers several useful services, for any nontrivial application you'll find it useful
to write your own custom services. To do this you begin by registering a service factory function
with a module either via the <a href="api/angular.module"><code>Module#factory api</code></a> or directly
via the <a href="api/AUTO.$provide"><code>$provide</code></a> api inside of module config function.</p>
<p>All Angular services participate in <a href="guide/di">dependency injection (DI)</a> by registering
themselves with Angular's DI system (injector) under a <code>name</code> (id) as well as by declaring
dependencies which need to be provided for the factory function of the registered service. The
ability to swap dependencies for mocks/stubs/dummies in tests allows for services to be highly
testable.</p>
<h2>Registering Services</h2>
<p>To register a service, you must have a module that this service will be part of. Afterwards, you
can register the service with the module either via the <a href="api/angular.Module"><code>Module api</code></a> or
by using the <a href="api/AUTO.$provide"><code>$provide</code></a> service in the module configuration
function.The following pseudo-code shows both approaches:</p>
<p>Using the angular.Module api:
<pre class="prettyprint linenums">
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
</pre>
<p>Using the $provide service:
<pre class="prettyprint linenums">
angular.module('myModule', [], function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
});
</pre>
<p>Note that you are not registering a service instance, but rather a factory function that will
create this instance when called.</p>
<h2>Dependencies</h2>
<p>Services can not only be depended upon, but can also have their own dependencies. These can be specified
as arguments of the factory function. <a href="guide/di">Read more</a> about dependency injection (DI)
in Angular and the use of array notation and the $inject property to make DI annotation
minification-proof.</p>
<p>Following is an example of a very simple service. This service depends on the <code>$window</code> service
(which is passed as a parameter to the factory function) and is just a function. The service simply
stores all notifications; after the third one, the service displays all of the notifications by
window alert.</p>
<pre class="prettyprint linenums">
angular.module('myModule', [], function($provide) {
$provide.factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
});
</pre>
<h2>Instantiating Angular Services</h2>
<p>All services in Angular are instantiated lazily. This means that a service will be created
only when it is needed for instantiation of a service or an application component that depends on it.
In other words, Angular won't instantiate services unless they are requested directly or
indirectly by the application.</p>
<h2>Services as singletons</h2>
<p>Lastly, it is important to realize that all Angular services are application singletons. This means
that there is only one instance of a given service per injector. Since Angular is lethally allergic
to global state, it is possible to create multiple injectors, each with its own instance of a
given service, but that is rarely needed, except in tests where this property is crucially
important.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.services.understanding_services">Understanding Angular Services</a></li>
<li><a href="guide/dev_guide.services.managing_dependencies">Managing Service Dependencies</a></li>
<li><a href="guide/dev_guide.services.injecting_controllers">Injecting Services Into Controllers</a></li>
<li><a href="guide/dev_guide.services.testing_services">Testing Angular Services</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng">Angular Service API</a></li>
</ul></div>

View file

@ -0,0 +1,22 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Services are a feature that Angular brings to client-side web apps from the server side, where
services have been commonly used for a long time. Services in Angular apps are substitutable
objects that are wired together using <a href="guide/di">dependency injection (DI)</a>.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.services.understanding_services">Understanding Angular Services</a></li>
<li><a href="guide/dev_guide.services.creating_services">Creating Angular Services</a></li>
<li><a href="guide/dev_guide.services.managing_dependencies">Managing Service Dependencies</a></li>
<li><a href="guide/dev_guide.services.injecting_controllers">Injecting Services Into Controllers</a></li>
<li><a href="guide/dev_guide.services.testing_services">Testing Angular Services</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng">Angular Service API</a></li>
</ul></div>

View file

@ -0,0 +1,138 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Using services as dependencies for controllers is very similar to using services as dependencies
for another service.</p>
<p>Since JavaScript is a dynamic language, DI can't figure out which services to inject by static
types (like in static typed languages). Therefore, you can specify the service name by using the
<code>$inject</code> property, which is an array containing strings with names of services to be injected.
The name must match the corresponding service ID registered with angular. The order of the service
IDs matters: the order of the services in the array 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, which has added benefits discussed below.</p>
<pre class="prettyprint linenums">
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>
<h3>Source</h3>
<div source-edit="MyServiceModule" source-edit-deps="angular.js script.js" source-edit-html="index.html-34" source-edit-css="" source-edit-js="script.js-33" source-edit-unit="" source-edit-scenario="scenario.js-35"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-34" ng-html-wrap="MyServiceModule angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-34">
<div ng-controller="myController">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-33"></pre>
<script type="text/ng-template" id="script.js-33">
angular.
module('MyServiceModule', []).
factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
function myController(scope, notifyService) {
scope.callNotify = function(msg) {
notifyService(msg);
};
}
myController.$inject = ['$scope','notify'];
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-35"></pre>
<script type="text/ng-template" id="scenario.js-35">
it('should test service', function() {
expect(element(':input[ng\\:model="message"]').val()).toEqual('test');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="MyServiceModule" ng-set-html="index.html-34" ng-eval-javascript="script.js-33"></div>
<h3>Implicit Dependency Injection</h3>
<p>A new feature of Angular DI allows it to determine the dependency from the name of the parameter.
Let's rewrite the above example to show the use of this implicit dependency injection of
<code>$window</code>, <code>$scope</code>, and our <code>notify</code> service:</p>
<h3>Source</h3>
<div source-edit="MyServiceModuleDI" source-edit-deps="angular.js script.js" source-edit-html="index.html-37" source-edit-css="" source-edit-js="script.js-36" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-37" ng-html-wrap="MyServiceModuleDI angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-37">
<div ng-controller="myController">
<p>Let's try the notify service, that is implicitly injected into the controller...</p>
<input ng-init="message='test'" ng-model="message">
<button ng-click="callNotify(message);">NOTIFY</button>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-36"></pre>
<script type="text/ng-template" id="script.js-36">
angular.
module('MyServiceModuleDI', []).
factory('notify', function($window) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
$window.alert(msgs.join("\n"));
msgs = [];
}
};
});
function myController($scope, notify) {
$scope.callNotify = function(msg) {
notify(msg);
};
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="MyServiceModuleDI" ng-set-html="index.html-37" ng-eval-javascript="script.js-36"></div>
<p>However, if you plan to <a href="http://en.wikipedia.org/wiki/Minification_(programming)">minify</a> your
code, your variable names will get renamed in which case you will still need to explicitly specify
dependencies with the <code>$inject</code> property.</p>
<h3>Related Topics</h3>
<p><a href="guide/dev_guide.services.understanding_services">Understanding Angular Services</a>
<a href="guide/dev_guide.services.creating_services">Creating Angular Services</a>
<a href="guide/dev_guide.services.managing_dependencies">Managing Service Dependencies</a>
<a href="guide/dev_guide.services.testing_services">Testing Angular Services</a></p>
<h3>Related API</h3>
<p><a href="api/ng">Angular Service API</a></p></div>

View file

@ -0,0 +1,113 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Angular allows services to declare other services as dependencies needed for construction of their
instances.</p>
<p>To declare dependencies, you specify them in the factory function signature and annotate the
function with the inject annotations either using by setting the <code>$inject</code> property, as an array of
string identifiers or using the array notation. Optionally the <code>$inject</code> property declaration can be
dropped (see "Inferring <code>$inject</code>" but note that that is currently an experimental feature).</p>
<p>Using the array notation:</p>
<pre class="prettyprint linenums">
function myModuleCfgFn($provide) {
$provide.factory('myService', ['dep1', 'dep2', function(dep1, dep2) {}]);
}
</pre>
<p>Using the $inject property:</p>
<pre class="prettyprint linenums">
function myModuleCfgFn($provide) {
var myServiceFactory = function(dep1, dep2) {};
myServiceFactory.$inject = ['dep1', 'dep2'];
$provide.factory('myService', myServiceFactory);
}
</pre>
<p>Using DI inference (incompatible with minifiers):</p>
<pre class="prettyprint linenums">
function myModuleCfgFn($provide) {
$provide.factory('myService', function(dep1, dep2) {});
}
</pre>
<p>Here is an example of two services, one of which depends on the other and both
of which depend on other services that are provided by the Angular framework:</p>
<pre class="prettyprint linenums">
/**
* batchLog service allows for messages to be queued in memory and flushed
* to the console.log every 50 seconds.
*
* @param {*} message Message to be logged.
*/
function batchLogModule($provide){
$provide.factory('batchLog', ['$timeout', '$log', function($timeout, $log) {
var messageQueue = [];
function log() {
if (messageQueue.length) {
$log('batchLog messages: ', messageQueue);
messageQueue = [];
}
$timeout(log, 50000);
}
// start periodic checking
log();
return function(message) {
messageQueue.push(message);
}
}]);
/**
* routeTemplateMonitor monitors each $route change and logs the current
* template via the batchLog service.
*/
$provide.factory('routeTemplateMonitor',
['$route', 'batchLog', '$rootScope',
function($route, batchLog, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function() {
batchLog($route.current ? $route.current.template : null);
});
}]);
}
// get the main service to kick of the application
angular.injector([batchLogModule]).get('routeTemplateMonitor');
</pre>
<p>Things to notice in this example:</p>
<ul>
<li>The <code>batchLog</code> service depends on the built-in <a href="api/ng.$timeout"><code>$timeout</code></a> and
<a href="api/ng.$log"><code>$log</code></a> services, and allows messages to be logged into the
<code>console.log</code> in batches.</li>
<li>The <code>routeTemplateMonitor</code> service depends on the built-in <a href="api/ng.$route"><code>$route</code></a> service as well as our custom <code>batchLog</code> service.</li>
<li>Both of our services use the factory function signature and array notation for inject annotations
to declare their dependencies. It is important that the order of the string identifiers in the array
is the same as the order of argument names in the signature of the factory function. Unless the
dependencies are inferred from the function signature, it is this array with IDs and their order
that the injector uses to determine which services and in which order to inject.</li>
</ul>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.services.understanding_services">Understanding Angular Services</a></li>
<li><a href="guide/dev_guide.services.creating_services">Creating Angular Services</a></li>
<li><a href="guide/dev_guide.services.injecting_controllers">Injecting Services Into Controllers</a></li>
<li><a href="guide/dev_guide.services.testing_services">Testing Angular Services</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng">Angular Service API</a></li>
<li><a href="api/angular.injector"><code>Angular Injector API</code></a></li>
</ul></div>

View file

@ -0,0 +1,63 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>The following is a unit test for the 'notify' service in the 'Dependencies' example in <a href="guide/dev_guide.services.creating_services">Creating Angular Services</a>. The unit test example uses Jasmine
spy (mock) instead of a real browser alert.</p>
<pre class="prettyprint linenums">
var mock, notify;
beforeEach(function() {
mock = {alert: jasmine.createSpy()};
module(function($provide) {
$provide.value('$window', mock);
});
inject(function($injector) {
notify = $injector.get('notify');
});
});
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>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.services.understanding_services">Understanding Angular Services</a></li>
<li><a href="guide/dev_guide.services.creating_services">Creating Angular Services</a></li>
<li><a href="guide/dev_guide.services.managing_dependencies">Managing Service Dependencies</a></li>
<li><a href="guide/dev_guide.services.injecting_controllers">Injecting Services Into Controllers</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng">Angular Service API</a></li>
</ul></div>

View file

@ -0,0 +1,39 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Angular services are singletons that carry out specific tasks common to web apps, such as the
<a href="api/ng.$http"><code>$http service</code></a> that provides low level access to the browser's
<code>XMLHttpRequest</code> object.</p>
<p>To use an Angular service, you identify it as a dependency for the dependent (a controller, or
another service) that depends on the service. Angular's dependency injection subsystem takes care
of the rest. The Angular injector subsystem is in charge of service instantiation, resolution of
dependencies, and provision of dependencies to factory functions as requested.</p>
<p>Angular injects dependencies using "constructor" injection (the service is passed in via a factory
function). Because JavaScript is a dynamically typed language, Angular's dependency injection
subsystem cannot use static types to identify service dependencies. For this reason a dependent
must explicitly define its dependencies by using the <code>$inject</code> property. For example:</p>
<pre><code> myController.$inject = ['$location'];
</code></pre>
<p>The Angular web framework provides a set of services for common operations. Like other core Angular
variables and identifiers, the built-in services always start with <code>$</code> (such as <code>$http</code> mentioned
above). You can also create your own custom services.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/di">About Angular Dependency Injection</a></li>
<li><a href="guide/dev_guide.services.creating_services">Creating Angular Services</a></li>
<li><a href="guide/dev_guide.services.managing_dependencies">Managing Service Dependencies</a></li>
<li><a href="guide/dev_guide.services.testing_services">Testing Angular Services</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng">Angular Service API</a></li>
<li><a href="api/angular.injector"><code>Injector API</code></a></li>
</ul></div>

View file

@ -0,0 +1,25 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Angular sets these CSS classes. It is up to your application to provide useful styling.</p>
<h2>CSS classes used by angular</h2>
<ul>
<li><p><code>ng-invalid</code>, <code>ng-valid</code></p>
<ul><li><strong>Usage:</strong> angular applies this class to an input widget element if that element's input does
not pass validation. (see <a href="api/ng.directive:input"><code>input</code></a> directive).</li></ul></li>
<li><p><code>ng-pristine</code>, <code>ng-dirty</code></p>
<ul><li><strong>Usage:</strong> angular <a href="api/ng.directive:input"><code>input</code></a> directive applies <code>ng-pristine</code> class
to a new input widget element which did not have user interaction. Once the user interacts with
the input widget the class is changed to <code>ng-dirty</code>.</li></ul></li>
</ul>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.templates">Angular Templates</a></li>
<li><a href="guide/forms">Angular Forms</a></li>
</ul></div>

View file

@ -0,0 +1,38 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Data-binding in Angular web apps is the automatic syncronization of data between the model and view
components. The way that Angular implements data-binding lets you treat the model as the
single-source-of-truth in your application. The view is a projection of the model at all times.
When the model changes, the view reflects the change, and vice versa.</p>
<h3>Data Binding in Classical Template Systems</h3>
<p><img class="right" src="img/One_Way_Data_Binding.png"/>
Most templating systems bind data in only one direction: they merge template and model components
together into a view, as illustrated in the diagram. After the merge occurs, changes to the model
or related sections of the view are NOT automatically reflected in the view. Worse, any changes
that the user makes to the view are not reflected in the model. This means that the developer has
to write code that constantly syncs the view with the model and the model with the view.</p>
<h3>Data Binding in Angular Templates</h3>
<p><img class="right" src="img/Two_Way_Data_Binding.png"/>
The way Angular templates works is different, as illustrated in the diagram. They are different
because first the template (which is the uncompiled HTML along with any additional markup or
directives) is compiled on the browser, and second, the compilation step produces a live view. We
say live because any changes to the view are immediately reflected in the model, and any changes in
the model are propagated to the view. This makes the model always the single-source-of-truth for
the application state, greatly simplifying the programming model for the developer. You can think of
the view as simply an instant projection of your model.</p>
<p>Because the view is just a projection of the model, the controller is completely separated from the
view and unaware of it. This makes testing a snap because it is easy to test your controller in
isolation without the view and the related DOM/browser dependency.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/scope">Angular Scopes</a></li>
<li><a href="guide/dev_guide.templates">Angular Templates</a></li>
</ul></div>

View file

@ -0,0 +1,74 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Writing your own filter is very easy: just register a new filter (injectable) factory function with
your module. This factory function should return a new filter function which takes the input value
as the first argument. Any filter arguments are passed in as additional arguments to the filter
function.</p>
<p>The following sample filter reverses a text string. In addition, it conditionally makes the
text upper-case and assigns color.</p>
<h3>Source</h3>
<div source-edit="MyReverseModule" source-edit-deps="angular.js script.js" source-edit-html="index.html-39" source-edit-css="" source-edit-js="script.js-38" source-edit-unit="" source-edit-scenario="scenario.js-40"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-39" ng-html-wrap="MyReverseModule angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-39">
<div ng-controller="Ctrl">
<input ng-model="greeting" type="greeting"><br>
No filter: {{greeting}}<br>
Reverse: {{greeting|reverse}}<br>
Reverse + uppercase: {{greeting|reverse:true}}<br>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-38"></pre>
<script type="text/ng-template" id="script.js-38">
angular.module('MyReverseModule', []).
filter('reverse', function() {
return function(input, uppercase) {
var out = "";
for (var i = 0; i < input.length; i++) {
out = input.charAt(i) + out;
}
// conditional based on optional argument
if (uppercase) {
out = out.toUpperCase();
}
return out;
}
});
function Ctrl($scope) {
$scope.greeting = 'hello';
}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-40"></pre>
<script type="text/ng-template" id="scenario.js-40">
it('should reverse greeting', function() {
expect(binding('greeting|reverse')).toEqual('olleh');
input('greeting').enter('ABC');
expect(binding('greeting|reverse')).toEqual('CBA');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="MyReverseModule" ng-set-html="index.html-39" ng-eval-javascript="script.js-38"></div>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.templates.filters">Understanding Angular Filters</a></li>
<li><a href="guide/compiler">Angular HTML Compiler</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng.$filter"><code>Angular Filter API</code></a></li>
</ul></div>

View file

@ -0,0 +1,28 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Angular filters format data for display to the user. In addition to formatting data, filters can
also modify the DOM. This allows filters to handle tasks such as conditionally applying CSS styles
to filtered output.</p>
<p>For example, you might have a data object that needs to be formatted according to the locale before
displaying it to the user. You can pass expressions through a chain of filters like this:</p>
<pre><code> name | uppercase
</code></pre>
<p>The expression evaluator simply passes the value of name to
<a href="api/ng.filter:uppercase"><code>uppercase filter</code></a>.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.templates.filters.using_filters">Using Angular Filters</a></li>
<li><a href="guide/dev_guide.templates.filters.creating_filters">Creating Angular Filters</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng.$filter"><code>Angular Filter API</code></a></li>
</ul></div>

View file

@ -0,0 +1,47 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Filters can be part of any <a href="api/ng.$rootScope.Scope"><code>api/ng.$rootScope.Scope</code></a> evaluation but are typically used to format
expressions in bindings in your templates:</p>
<pre><code> {{ expression | filter }}
</code></pre>
<p>Filters typically transform the data to a new data type, formatting the data in the process.
Filters can also be chained, and can take optional arguments.</p>
<p>You can chain filters using this syntax:</p>
<pre><code> {{ expression | filter1 | filter2 }}
</code></pre>
<p>You can also pass colon-delimited arguments to filters, for example, to display the number 123 with
2 decimal points:</p>
<pre><code> 123 | number:2
</code></pre>
<p>Here are some examples that show values before and after applying different filters to an
expression in a binding:</p>
<ul>
<li>No filter: <code>{{1234.5678}}</code> => <code>1234.5678</code></li>
<li>Number filter: <code>{{1234.5678|number}}</code> => <code>1,234.57</code>. Notice the "," and rounding to two
significant digits.</li>
<li>Filter with arguments: <code>{{1234.5678|number:5}}</code> => <code>1,234.56780</code>. Filters can take optional
arguments, separated by colons in a binding. For example, the "number" filter takes a number
argument that specifies how many digits to display to the right of the decimal point.</li>
</ul>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.templates.filters">Understanding Angular Filters</a></li>
<li><a href="guide/dev_guide.templates.filters.creating_filters">Creating Angular Filters</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/ng.$filter"><code>Angular Filter API</code></a></li>
</ul></div>

View file

@ -0,0 +1,60 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>An Angular template is the declarative specification that, along with information from the model
and controller, becomes the rendered view that a user sees in the browser. It is the static DOM,
containing HTML, CSS, and angular-specific elements and angular-specific element attributes. The
Angular elements and attributes direct angular to add behavior and transform the template DOM into
the dynamic view DOM.</p>
<p>These are the types of Angular elements and element attributes you can use in a template:</p>
<ul>
<li><a href="guide/directive">Directive</a> — An attribute or element that
augments an existing DOM element or represents a reusable DOM component - a widget.</li>
<li><a href="api/ng.$interpolate"><code>Markup</code></a> — The double
curly brace notation <code>{{ }}</code> to bind expressions to elements is built-in angular markup.</li>
<li><a href="guide/dev_guide.templates.filters">Filter</a> — Formats your data for display to the user.</li>
<li><a href="guide/forms">Form controls</a> — Lets you validate user input.</li>
</ul>
<p>Note: In addition to declaring the elements above in templates, you can also access these elements
in JavaScript code.</p>
<p>The following code snippet shows a simple Angular template made up of standard HTML tags along with
Angular <a href="guide/directive">directives</a> and curly-brace bindings
with <a href="guide/expression">expressions</a>:</p>
<pre class="prettyprint linenums">
&lt;html ng-app&gt;
&lt;!-- Body tag augmented with ngController directive --&gt;
&lt;body ng-controller="MyController"&gt;
&lt;input ng-model="foo" value="bar"&gt;
&lt;!-- Button tag with ng-click directive, and
string expression 'buttonText'
wrapped in "{{ }}" markup --&gt;
&lt;button ng-click="changeFoo()"&gt;{{buttonText}}&lt;/button&gt;
&lt;script src="angular.js"&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In a simple single-page app, the template consists of HTML, CSS, and angular directives contained
in just one HTML file (usually <code>index.html</code>). In a more complex app, you can display multiple views
within one main page using "partials", which are segments of template located in separate HTML
files. You "include" the partials in the main page using the <a href="api/ng.$route"><code>$route</code></a> service in conjunction with the <a href="api/ng.directive:ngView"><code>ngView</code></a> directive. An
example of this technique is shown in the <a href="tutorial/index">angular tutorial</a>, in steps seven and
eight.</p>
<h3>Related Topics</h3>
<ul>
<li><a href="guide/dev_guide.templates.filters">Angular Filters</a></li>
<li><a href="guide/forms">Angular Forms</a></li>
</ul>
<h3>Related API</h3>
<ul>
<li><a href="api/index">API Reference</a></li>
</ul></div>

View file

@ -0,0 +1,302 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
Angular which makes testing your Angular applications easy. So there is no excuse for not testing.</p>
<h2>It is all about NOT mixing concerns</h2>
<p>Unit testing as the name implies is about testing individual units of code. Unit tests try to
answer questions such as "Did I think about the logic correctly?" or "Does the sort function order the list
in the right order?"</p>
<p>In order to answer such question it is very important that we can isolate the unit of code under test.
That is because when we are testing the sort function we don't want to be forced into creating
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort.</p>
<p>While
this may seem obvious it usually is very difficult to be able to call an individual function on a
typical project. The reason is that the developers often mix concerns, and they end up with a
piece of code which does everything. It reads the data from XHR, it sorts it and then it
manipulates the DOM.</p>
<p>With Angular we try to make it easy for you to do the right thing, and so we
provide dependency injection for your XHR (which you can mock out) and we created abstraction which
allow you to sort your model without having to resort to manipulating the DOM. So that in the end,
it is easy to write a sort function which sorts some data, so that your test can create a data set,
apply the function, and assert that the resulting model is in the correct order. The test does not
have to wait for XHR, or create the right kind of DOM, or assert that your function has mutated the
DOM in the right way.</p>
<h3>With great power comes great responsibility</h3>
<p>Angular is written with testability in mind, but it still requires that you
do the right thing. We tried to make the right thing easy, but Angular is not magic, which means if
you don't follow these guidelines you may very well end up with an untestable application.</p>
<h3>Dependency Injection</h3>
<p>There are several ways in which you can get a hold of a dependency:
1. You could create it using the <code>new</code> operator.
2. You could look for it in a well known place, also known as global singleton.
3. You could ask a registry (also known as service registry) for it. (But how do you get a hold of
the registry? Most likely by looking it up in a well known place. See #2)
4. You could expect that it be handed to you.</p>
<p>Out of the four options in the list above, only the last one is testable. Let's look at why:</p>
<h4>Using the <code>new</code> operator</h4>
<p>While there is nothing wrong with the <code>new</code> operator fundamentally the issue is that calling a new
on a constructor permanently binds the call site to the type. For example lets say that we are
trying to instantiate an <code>XHR</code> so that we can get some data from the server.</p>
<pre class="prettyprint linenums">
function MyClass() {
this.doWork = function() {
var xhr = new XHR();
xhr.open(method, url, true);
xhr.onreadystatechange = function() {...}
xhr.send();
}
}
</pre>
<p>The issue becomes that in tests, we would very much like to instantiate a <code>MockXHR</code> which would
allow us to return fake data and simulate network failures. By calling <code>new XHR()</code> we are
permanently bound to the actual XHR, and there is no good way to replace it. Yes there is monkey
patching. That is a bad idea for many reasons which are outside the scope of this document.</p>
<p>The class above is hard to test since we have to resort to monkey patching:
<pre class="prettyprint linenums">
var oldXHR = XHR;
XHR = function MockXHR() {};
var myClass = new MyClass();
myClass.doWork();
// assert that MockXHR got called with the right arguments
XHR = oldXHR; // if you forget this bad things will happen
</pre>
<h4>Global look-up:</h4>
<p>Another way to approach the problem is to look for the service in a well known location.</p>
<pre class="prettyprint linenums">
function MyClass() {
this.doWork = function() {
global.xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
}
</pre>
<p>While no new instance of the dependency is being created, it is fundamentally the same as <code>new</code>, in
that there is no good way to intercept the call to <code>global.xhr</code> for testing purposes, other then
through monkey patching. The basic issue for testing is that global variable needs to be mutated in
order to replace it with call to a mock method. For further explanation why this is bad see: <a href="http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/">Brittle Global State &amp; Singletons</a></p>
<p>The class above is hard to test since we have to change global state:
<pre class="prettyprint linenums">
var oldXHR = global.xhr;
global.xhr = function mockXHR() {};
var myClass = new MyClass();
myClass.doWork();
// assert that mockXHR got called with the right arguments
global.xhr = oldXHR; // if you forget this bad things will happen
</pre>
<h4>Service Registry:</h4>
<p>It may seem as that this can be solved by having a registry for all of the services, and then
having the tests replace the services as needed.</p>
<pre class="prettyprint linenums">
function MyClass() {
var serviceRegistry = ????;
this.doWork = function() {
var xhr = serviceRegistry.get('xhr');
xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
</pre>
<p>However, where does the serviceRegistry come from? if it is:
* <code>new</code>-ed up, the the test has no chance to reset the services for testing
* global look-up, then the service returned is global as well (but resetting is easier, since
there is only one global variable to be reset).</p>
<p>The class above is hard to test since we have to change global state:
<pre class="prettyprint linenums">
var oldServiceLocator = global.serviceLocator;
global.serviceLocator.set('xhr', function mockXHR() {});
var myClass = new MyClass();
myClass.doWork();
// assert that mockXHR got called with the right arguments
global.serviceLocator = oldServiceLocator; // if you forget this bad things will happen
</pre>
<h4>Passing in Dependencies:</h4>
<p>Lastly the dependency can be passed in.</p>
<pre class="prettyprint linenums">
function MyClass(xhr) {
this.doWork = function() {
xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
</pre>
<p>This is the preferred way since the code makes no assumptions as to where the <code>xhr</code> comes from,
rather that whoever created the class was responsible for passing it in. Since the creator of the
class should be different code than the user of the class, it separates the responsibility of
creation from the logic, and that is what dependency-injection is in a nutshell.</p>
<p>The class above is very testable, since in the test we can write:
<pre class="prettyprint linenums">
function xhrMock(args) {...}
var myClass = new MyClass(xhrMock);
myClass.doWork();
// assert that xhrMock got called with the right arguments
</pre>
<p>Notice that no global variables were harmed in the writing of this test.</p>
<p>Angular comes with <a href="guide/di">dependency injection</a> built in which makes the right thing
easy to do, but you still need to do it if you wish to take advantage of the testability story.</p>
<h3>Controllers</h3>
<p>What makes each application unique is its logic, which is what we would like to test. If the logic
for your application is mixed in with DOM manipulation, it will be hard to test as in the example
below:</p>
<pre class="prettyprint linenums">
function PasswordCtrl() {
// get references to DOM elements
var msg = $('.ex1 span');
var input = $('.ex1 input');
var strength;
this.grade = function() {
msg.removeClass(strength);
var pwd = input.val();
password.text(pwd);
if (pwd.length &gt; 8) {
strength = 'strong';
} else if (pwd.length &gt; 3) {
strength = 'medium';
} else {
strength = 'weak';
}
msg
.addClass(strength)
.text(strength);
}
}
</pre>
<p>The code above is problematic from a testability point of view, since it requires your test to have the right kind
of DOM present when the code executes. The test would look like this:</p>
<pre class="prettyprint linenums">
var input = $('&lt;input type="text"/&gt;');
var span = $('&lt;span&gt;');
$('body').html('&lt;div class="ex1"&gt;')
.find('div')
.append(input)
.append(span);
var pc = new PasswordCtrl();
input.val('abc');
pc.grade();
expect(span.text()).toEqual('weak');
$('body').html('');
</pre>
<p>In angular the controllers are strictly separated from the DOM manipulation logic which results in
a much easier testability story as can be seen in this example:</p>
<pre class="prettyprint linenums">
function PasswordCtrl($scope) {
$scope.password = '';
$scope.grade = function() {
var size = $scope.password.length;
if (size &gt; 8) {
$scope.strength = 'strong';
} else if (size &gt; 3) {
$scope.strength = 'medium';
} else {
$scope.strength = 'weak';
}
};
}
</pre>
<p>and the test is straight forward</p>
<pre class="prettyprint linenums">
var pc = new PasswordCtrl();
pc.password('abc');
pc.grade();
expect(pc.strength).toEqual('weak');
</pre>
<p>Notice that the test is not only much shorter but it is easier to follow what is going on. We say
that such a test tells a story, rather then asserting random bits which don't seem to be related.</p>
<h3>Filters</h3>
<p><a href="api/ng.$filter"><code>Filters</code></a> are functions which transform the data into user readable
format. They are important because they remove the formatting responsibility from the application
logic, further simplifying the application logic.</p>
<pre class="prettyprint linenums">
myModule.filter('length', function() {
return function(text){
return (''+(text||'')).length;
}
});
var length = $filter('length');
expect(length(null)).toEqual(0);
expect(length('abc')).toEqual(3);
</pre>
<h3>Directives</h3>
<p>Directives in angular are responsible for updating the DOM when the state of the model changes.</p>
<h3>Mocks</h3>
<p>oue</p>
<h3>Global State Isolation</h3>
<p>oue</p>
<h2>Preferred way of Testing</h2>
<p>uo</p>
<h3>JavaScriptTestDriver</h3>
<p>ou</p>
<h3>Jasmine</h3>
<p>ou</p>
<h3>Sample project</h3>
<p>uoe</p></div>

View file

@ -0,0 +1,223 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>Dependency Injection</h2>
<p>Dependency Injection (DI) is a software design pattern that deals with how code gets hold of its
dependencies.</p>
<p>For in-depth discussion about DI, see <a href="http://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> at Wikipedia, <a href="http://martinfowler.com/articles/injection.html">Inversion of Control</a> by Martin Fowler, or read about DI in your favorite software design pattern
book.</p>
<h3>DI in a nutshell</h3>
<p>There are only three ways how an object or a function can get a hold of its dependencies:</p>
<ol>
<li><p>The dependency can be created, typically using the <code>new</code> operator.</p></li>
<li><p>The dependency can be looked up by referring to a global variable.</p></li>
<li><p>The dependency can be passed in to where it is needed.</p></li>
</ol>
<p>The first two option of creating or looking up dependencies are not optimal, because they hard
code the dependency, making it difficult, if not impossible, to modify the dependencies.
This is especially problematic in tests, where it is often desirable to provide mock dependencies
for test isolation.</p>
<p>The third option is the most viable, since it removes the responsibility of locating the
dependency from the component. The dependency is simply handed to the component.</p>
<pre class="prettyprint linenums">
function SomeClass(greeter) {
this.greeter = greeter
}
SomeClass.prototype.doSomething = function(name) {
this.greeter.greet(name);
}
</pre>
<p>In the above example the <code>SomeClass</code> is not concerned with locating the <code>greeter</code> dependency, it
is simply handed the <code>greeter</code> at runtime.</p>
<p>This is desirable, but it puts the responsibility of getting hold of the dependency onto the
code responsible for the construction of <code>SomeClass</code>.</p>
<p>To manage the responsibility of dependency creation, each Angular application has an <a href="api/angular.injector"><code>injector</code></a>. The injector is a service locator that is responsible for
construction and lookup of dependencies.</p>
<p>Here is an example of using the injector service.
<pre class="prettyprint linenums">
// Provide the wiring information in a module
angular.module('myModule', []).
// Teach the injector how to build a 'greeter'
// Notice that greeter itself is dependent on '$window'
factory('greeter', function($window) {
// This is a factory function, and is responsible for
// creating the 'greet' service.
return {
greet: function(text) {
$window.alert(text);
}
};
});
// New injector is created from the module.
// (This is usually done automatically by angular bootstrap)
var injector = angular.injector(['myModule', 'ng']);
// Request any dependency from the injector
var greeter = injector.get('greeter');
</pre>
<p>Asking for dependencies solves the issue of hard coding, but it also means that the injector needs
to be passed throughout the application. Passing the injector breaks the <a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>. To remedy this, we turn the
dependency lookup responsibility to the injector by declaring the dependencies as in this example:</p>
<pre class="prettyprint linenums">
&lt;!-- Given this HTML --&gt;
&lt;div ng-controller="MyController"&gt;
&lt;button ng-click="sayHello()"&gt;Hello&lt;/button&gt;
&lt;/div&gt;
</pre> <br />
<pre class="prettyprint linenums">
// And this controller definition
function MyController($scope, greeter) {
$scope.sayHello = function() {
greeter.greet('Hello World');
};
}
// The 'ng-controller' directive does this behind the scenes
injector.instantiate(MyController);
</pre>
<p>Notice that by having the <code>ng-controller</code> instantiate the class, it can satisfy all of the
dependencies of the <code>MyController</code> without the controller ever knowing about the injector. This is
the best outcome. The application code simply ask for the dependencies it needs, without having to
deal with the injector. This setup does not break the Law of Demeter.</p>
<h2>Dependency Annotation</h2>
<p>How does the injector know what service needs to be injected? </p>
<p>The application developer needs to provide annotation information that the injector uses in order
to resolve the dependencies. Throughout Angular certain API functions are invoked using the
injector, as per the API documentation. The injector needs to know what services to inject into
the function. Below are three equivalent ways of annotating your code with service name
information. These can be used interchangeably as you see fit and are equivalent.</p>
<h2>Inferring Dependencies</h2>
<p>The simplest way to get hold of the dependencies, is to assume that the function parameter names
are the names of the dependencies.</p>
<pre class="prettyprint linenums">
function MyController($scope, greeter) {
...
}
</pre>
<p>Given a function the injector can infer the names of the service to inject by examining the
function declaration and extracting the parameter names. In the above example <code>$scope</code>, and
<code>greeter</code> are two services which need to be injected into the function.</p>
<p>While straightforward, this method will not work with JavaScript minifiers/obfuscators as they
rename the method parameter names. This makes this way of annotating only useful for <a href="http://www.pretotyping.org/">pretotyping</a>, and demo applications.</p>
<h2><code>$inject</code> Annotation</h2>
<p>To allow the minifers to rename the function parameters and still be able to inject right services
the function needs to be annotate with the <code>$inject</code> property. The <code>$inject</code> property is an array
of service names to inject.</p>
<pre class="prettyprint linenums">
var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController.$inject = ['$scope', 'greeter'];
</pre>
<p>Care must be taken that the <code>$inject</code> annotation is kept in sync with the actual arguments in the
function declaration.</p>
<p>This method of annotation is useful for controller declarations since it assigns the annotation
information with the function.</p>
<h2>Inline Annotation</h2>
<p>Sometimes using the <code>$inject</code> annotation style is not convenient such as when annotating
directives.</p>
<p>For example:
<pre class="prettyprint linenums">
someModule.factory('greeter', function($window) {
...;
});
</pre>
<p>Results in code bloat due to the need of temporary variable:
<pre class="prettyprint linenums">
var greeterFactory = function(renamed$window) {
...;
};
greeterFactory.$inject = ['$window'];
someModule.factory('greeter', greeterFactory);
</pre>
<p>For this reason the third annotation style is provided as well.
<pre class="prettyprint linenums">
someModule.factory('greeter', ['$window', function(renamed$window) {
...;
}]);
</pre>
<p>Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
where injection is supported.</p>
<h2>Where can I use DI?</h2>
<p>DI is pervasive throughout Angular. It is typically used in controllers and factory methods. </p>
<h3>DI in controllers</h3>
<p>Controllers are classes which are responsible for application behavior. The recommended way of
declaring controllers is:</p>
<pre class="prettyprint linenums">
var MyController = function($scope, dep1, dep2) {
...
$scope.aMethod = function() {
...
}
}
MyController.$inject = ['$scope', 'dep1', 'dep2'];
</pre>
<h3>Factory methods</h3>
<p>Factory methods are responsible for creating most objects in Angular. Examples are directives,
services, and filters. The factory methods are registered with the module, and the recommended way
of declaring factories is:</p>
<pre class="prettyprint linenums">
angualar.module('myModule', []).
config(['depProvider', function(depProvider){
...
}]).
factory('serviceId', ['depService', function(depService) {
...
}]).
directive('directiveName', ['depService', function(depService) {
...
}]).
filter('filterName', ['depService', function(depService) {
...
}]).
run(['depService', function(depService) {
...
}]);
</pre></div>

View file

@ -0,0 +1,694 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Directives are a way to teach HTML new tricks. During DOM compilation directives are matched
against the HTML and executed. This allows directives to register behavior, or transform the DOM.</p>
<p>Angular comes with a built in set of directives which are useful for building web applications but
can be extended such that HTML can be turned into a declarative domain specific language (DSL).</p>
<h2>Invoking directives from HTML</h2>
<p>Directives have camel cased names such as <code>ngBind</code>. The directive can be invoked by translating
the camel case name into snake case with these special characters <code>:</code>, <code>-</code>, or <code>_</code>. Optionally the
directive can be prefixed with <code>x-</code>, or <code>data-</code> to make it HTML validator compliant. Here is a
list of some of the possible directive names: <code>ng:bind</code>, <code>ng-bind</code>, <code>ng_bind</code>, <code>x-ng-bind</code> and
<code>data-ng-bind</code>.</p>
<p>The directives can be placed in element names, attributes, class names, as well as comments. Here
are some equivalent examples of invoking <code>myDir</code>. (However, most directives are restricted to
attribute only.)</p>
<pre class="prettyprint linenums">
&lt;span my-dir="exp"&gt;&lt;/span&gt;
&lt;span class="my-dir: exp;"&gt;&lt;/span&gt;
&lt;my-dir&gt;&lt;/my-dir&gt;
&lt;!-- directive: my-dir exp --&gt;
</pre>
<p>Directives can be invoked in many different ways, but are equivalent in the end result as shown in
the following example.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-42" source-edit-css="" source-edit-js="script.js-41" source-edit-unit="" source-edit-scenario="scenario.js-43"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-42" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-42">
<div ng-controller="Ctrl1">
Hello <input ng-model='name'> <hr/>
&ltspan ng:bind="name"&gt <span ng:bind="name"></span> <br/>
&ltspan ng_bind="name"&gt <span ng_bind="name"></span> <br/>
&ltspan ng-bind="name"&gt <span ng-bind="name"></span> <br/>
&ltspan data-ng-bind="name"&gt <span data-ng-bind="name"></span> <br/>
&ltspan x-ng-bind="name"&gt <span x-ng-bind="name"></span> <br/>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-41"></pre>
<script type="text/ng-template" id="script.js-41">
function Ctrl1($scope) {
$scope.name = 'angular';
}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-43"></pre>
<script type="text/ng-template" id="scenario.js-43">
it('should show off bindings', function() {
expect(element('div[ng-controller="Ctrl1"] span[ng-bind]').text()).toBe('angular');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-42" ng-eval-javascript="script.js-41"></div>
<h2>String interpolation</h2>
<p>During the compilation process the <a href="api/ng.$compile"><code>compiler</code></a> matches text and
attributes using the <a href="api/ng.$interpolate"><code>$interpolate</code></a> service to see if they
contain embedded expressions. These expressions are registered as <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a> and will update as part of normal <a href="api/ng.$rootScope.Scope#$digest"><code>digest</code></a> cycle. An example of interpolation is shown
here:</p>
<pre class="prettyprint linenums">
&lt;a href="img/{{username}}.jpg"&gt;Hello {{username}}!&lt;/a&gt;
</pre>
<h2>Compilation process, and directive matching</h2>
<p>Compilation of HTML happens in three phases:</p>
<ol>
<li><p>First the HTML is parsed into DOM using the standard browser API. This is important to
realize because the templates must be parsable HTML. This is in contrast to most templating
systems that operate on strings, rather than on DOM elements.</p></li>
<li><p>The compilation of the DOM is performed by the call to the <a href="api/ng.$compile"><code>$compile()</code></a> method. The method traverses the DOM and matches the directives. If a match is found
it is added to the list of directives associated with the given DOM element. Once all directives
for a given DOM element have been identified they are sorted by priority and their <code>compile()</code>
functions are executed. The directive compile function has a chance to modify the DOM structure
and is responsible for producing a <code>link()</code> function explained next. The <a href="api/ng.$compile"><code>$compile()</code></a> method returns a combined linking function, which is a
collection of all of the linking functions returned from the individual directive compile
functions.</p></li>
<li><p>Link the template with scope by calling the linking function returned from the previous step.
This in turn will call the linking function of the individual directives allowing them to
register any listeners on the elements and set up any <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a> with the <a href="api/ng.$rootScope.Scope"><code>scope</code></a>. The result of this is a live binding between the
scope and the DOM. A change in the scope is reflected in the DOM.</p></li>
</ol>
<pre class="prettyprint linenums">
var $compile = ...; // injected into your code
var scope = ...;
var html = '&lt;div ng-bind='exp'&gt;&lt;/div&gt;';
// Step 1: parse HTML into DOM element
var template = angular.element(html);
// Step 2: compile the template
var linkFn = $compile(template);
// Step 3: link the compiled template with the scope.
linkFn(scope);
</pre>
<h3>Reasons behind the compile/link separation</h3>
<p>At this point you may wonder why the compile process is broken down to a compile and link phase.
To understand this, let's look at a real world example with a repeater:</p>
<pre class="prettyprint linenums">
Hello {{user}}, you have these actions:
&lt;ul&gt;
&lt;li ng-repeat="action in user.actions"&gt;
{{action.description}}
&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>The short answer is that compile and link separation is needed any time a change in model causes
a change in DOM structure such as in repeaters.</p>
<p>When the above example is compiled, the compiler visits every node and looks for directives. The
<code>{{user}}</code> is an example of an <a href="api/ng.$interpolate"><code>interpolation</code></a> directive. <a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a> is another directive. But <a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a> has a dilemma. It needs to be
able to quickly stamp out new <code>li</code>s for every <code>action</code> in <code>user.actions</code>. This means that it needs
to save a clean copy of the <code>li</code> element for cloning purposes and as new <code>action</code>s are inserted,
the template <code>li</code> element needs to be cloned and inserted into <code>ul</code>. But cloning the <code>li</code> element
is not enough. It also needs to compile the <code>li</code> so that its directives such as
<code>{{action.descriptions}}</code> evaluate against the right <a href="api/ng.$rootScope.Scope"><code>scope</code></a>. A naive method would be to simply insert a copy of the <code>li</code> element and then compile it.
But compiling on every <code>li</code> element clone would be slow, since the compilation requires that we
traverse the DOM tree and look for directives and execute them. If we put the compilation inside a
repeater which needs to unroll 100 items we would quickly run into performance problems.</p>
<p>The solution is to break the compilation process into two phases; the compile phase where all of
the directives are identified and sorted by priority, and a linking phase where any work which
links a specific instance of the <a href="api/ng.$rootScope.Scope"><code>scope</code></a> and the specific
instance of an <code>li</code> is performed.</p>
<p><a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a> works by preventing the
compilation process from descending into the <code>li</code> element. Instead the <a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a> directive compiles <code>li</code>
separately. The result of the <code>li</code> element compilation is a linking function which contains all
of the directives contained in the <code>li</code> element, ready to be attached to a specific clone of the <code>li</code>
element. At runtime the <a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a>
watches the expression and as items are added to the array it clones the <code>li</code> element, creates a
new <a href="api/ng.$rootScope.Scope"><code>scope</code></a> for the cloned <code>li</code> element and calls the
link function on the cloned <code>li</code>.</p>
<p>Summary:</p>
<ul>
<li><p><em>compile function</em> - The compile function is relatively rare in directives, since most
directives are concerned with working with a specific DOM element instance rather than
transforming the template DOM element. Any operation which can be shared among the instance of
directives should be moved to the compile function for performance reasons.</p></li>
<li><p><em>link function</em> - It is rare for the directive not to have a link function. A link function
allows the directive to register listeners to the specific cloned DOM element instance as well
as to copy content into the DOM from the scope.</p></li>
</ul>
<h2>Writing directives (short version)</h2>
<p>In this example we will build a directive that displays the current time.</p>
<h3>Source</h3>
<div source-edit="time" source-edit-deps="angular.js script.js" source-edit-html="index.html-45" source-edit-css="" source-edit-js="script.js-44" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-45" ng-html-wrap="time angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-45">
<div ng-controller="Ctrl2">
Date format: <input ng-model="format"> <hr/>
Current time is: <span my-current-time="format"></span>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-44"></pre>
<script type="text/ng-template" id="script.js-44">
function Ctrl2($scope) {
$scope.format = 'M/d/yy h:mm:ss a';
}
angular.module('time', [])
// Register the 'myCurrentTime' directive factory method.
// We inject $timeout and dateFilter service since the factory method is DI.
.directive('myCurrentTime', function($timeout, dateFilter) {
// return the directive link function. (compile function not needed)
return function(scope, element, attrs) {
var format, // date format
timeoutId; // timeoutId, so that we can cancel the time updates
// used to update the UI
function updateTime() {
element.text(dateFilter(new Date(), format));
}
// watch the expression, and update the UI on change.
scope.$watch(attrs.myCurrentTime, function(value) {
format = value;
updateTime();
});
// schedule update in one second
function updateLater() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
updateLater(); // schedule another update
}, 1000);
}
// listen on DOM destroy (removal) event, and cancel the next UI update
// to prevent updating time ofter the DOM element was removed.
element.bind('$destroy', function() {
$timeout.cancel(timeoutId);
});
updateLater(); // kick off the UI update process.
}
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="time" ng-set-html="index.html-45" ng-eval-javascript="script.js-44"></div>
<h2>Writing directives (long version)</h2>
<p>An example skeleton of the directive is shown here, for the complete list see below.</p>
<pre class="prettyprint linenums">
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '&lt;div&gt;&lt;/div&gt;',
templateUrl: 'directive.html',
replace: false,
transclude: false,
restrict: 'A',
scope: false,
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
},
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
});
</pre>
<p>In most cases you will not need such fine control and so the above can be simplified. All of the
different parts of this skeleton are explained in following sections. In this section we are
interested only in some of this skeleton.</p>
<p>The first step in simplyfing the code is to rely on the default values. Therefore the above can be
simplified as:</p>
<pre class="prettyprint linenums">
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
compile: function compile(tElement, tAttrs) {
return function postLink(scope, iElement, iAttrs) { ... }
}
};
return directiveDefinitionObject;
});
</pre>
<p>Most directives concern themselves only with instances, not with template transformations, allowing
further simplification:</p>
<pre class="prettyprint linenums">
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
return function postLink(scope, iElement, iAttrs) { ... }
});
</pre>
<h3>Factory method</h3>
<p>The factory method is responsible for creating the directive. It is invoked only once, when the
<a href="api/ng.$compile"><code>compiler</code></a> matches the directive for the first time. You can
perform any initialization work here. The method is invoked using the <a href="api/AUTO.$injector#invoke"><code>$injector.invoke</code></a> which
makes it injectable following all of the rules of injection annotation.</p>
<h3>Directive Definition Object</h3>
<p>The directive definition object provides instructions to the <a href="api/ng.$compile"><code>compiler</code></a>. The attributes are:</p>
<ul>
<li><p><code>name</code> - Name of the current scope. Optional and defaults to the name at registration.</p></li>
<li><p><code>priority</code> - When there are multiple directives defined on a single DOM element, sometimes it
is necessary to specify the order in which the directives are applied. The <code>priority</code> is used
to sort the directives before their <code>compile</code> functions get called. Higher <code>priority</code> goes
first. The order of directives within the same priority is undefined.</p></li>
<li><p><code>terminal</code> - If set to true then the current <code>priority</code> will be the last set of directives
which will execute (any directives at the current priority will still execute
as the order of execution on same <code>priority</code> is undefined).</p></li>
<li><p><code>scope</code> - If set to:</p>
<ul><li><p><code>true</code> - then a new scope will be created for this directive. If multiple directives on the
same element request a new scope, only one new scope is created. The new scope rule does not
apply for the root of the template since the root of the template always gets a new scope.</p></li>
<li><p><code>{}</code> (object hash) - then a new 'isolate' scope is created. The 'isolate' scope differs from
normal scope in that it does not prototypically inherit from the parent scope. This is useful
when creating reusable components, which should not accidentally read or modify data in the
parent scope. <br/>
The 'isolate' scope takes an object hash which defines a set of local scope properties
derived from the parent scope. These local properties are useful for aliasing values for
templates. Locals definition is a hash of local scope property to its source:</p>
<ul><li><p><code>@</code> or <code>@attr</code> - bind a local scope property to the value of DOM attribute. The result is
always a string since DOM attributes are strings. If no <code>attr</code> name is specified then the
attribute name is assumed to be the same as the local name.
Given <code>&lt;widget my-attr="hello {{name}}"&gt;</code> and widget definition
of <code>scope: { localName:'@myAttr' }</code>, then widget scope property <code>localName</code> will reflect
the interpolated value of <code>hello {{name}}</code>. As the <code>name</code> attribute changes so will the
<code>localName</code> property on the widget scope. The <code>name</code> is read from the parent scope (not
component scope).</p></li>
<li><p><code>=</code> or <code>=attr</code> - set up bi-directional binding between a local scope property and the
parent scope property of name defined via the value of the <code>attr</code> attribute. If no <code>attr</code>
name is specified then the attribute name is assumed to be the same as the local name.
Given <code>&lt;widget my-attr="parentModel"&gt;</code> and widget definition of
<code>scope: { localModel:'=myAttr' }</code>, then widget scope property <code>localModel</code> will reflect the
value of <code>parentModel</code> on the parent scope. Any changes to <code>parentModel</code> will be reflected
in <code>localModel</code> and any changes in <code>localModel</code> will reflect in <code>parentModel</code>.</p></li>
<li><p><code>&amp;</code> or <code>&amp;attr</code> - provides a way to execute an expression in the context of the parent scope.
If no <code>attr</code> name is specified then the attribute name is assumed to be the same as the
local name. Given <code>&lt;widget my-attr="count = count + value"&gt;</code> and widget definition of
<code>scope: { localFn:'&amp;myAttr' }</code>, then isolate scope property <code>localFn</code> will point to
a function wrapper for the <code>count = count + value</code> expression. Often it's desirable to
pass data from the isolated scope via an expression and to the parent scope, this can be
done by passing a map of local variable names and values into the expression wrapper fn.
For example, if the expression is <code>increment(amount)</code> then we can specify the amount value
by calling the <code>localFn</code> as <code>localFn({amount: 22})</code>.</p></li></ul></li></ul></li>
<li><p><code>controller</code> - Controller constructor function. The controller is instantiated before the
pre-linking phase and it is shared with other directives if they request it by name (see
<code>require</code> attribute). This allows the directives to communicate with each other and augment
each other's behavior. The controller is injectable with the following locals:</p>
<ul><li><code>$scope</code> - Current scope associated with the element</li>
<li><code>$element</code> - Current element</li>
<li><code>$attrs</code> - Current attributes obeject for the element</li>
<li><code>$transclude</code> - A transclude linking function pre-bound to the correct transclusion scope:
<code>function(cloneLinkingFn)</code>.</li></ul></li>
<li><p><code>require</code> - Require another controller be passed into current directive linking function. The
<code>require</code> takes a name of the directive controller to pass in. If no such controller can be
found an error is raised. The name can be prefixed with:</p>
<ul><li><code>?</code> - Don't raise an error. This makes the require dependency optional.</li>
<li><code>^</code> - Look for the controller on parent elements as well.</li></ul></li>
<li><p><code>restrict</code> - String of subset of <code>EACM</code> which restricts the directive to a specific directive
declaration style. If omitted directives are allowed on attributes only.</p>
<ul><li><code>E</code> - Element name: <code>&lt;my-directive&gt;&lt;/my-directive&gt;</code></li>
<li><code>A</code> - Attribute: <code>&lt;div my-directive="exp"&gt;
&lt;/div&gt;</code></li>
<li><code>C</code> - Class: <code>&lt;div class="my-directive: exp;"&gt;&lt;/div&gt;</code></li>
<li><code>M</code> - Comment: <code>&lt;!-- directive: my-directive exp --&gt;</code></li></ul></li>
<li><p><code>template</code> - replace the current element with the contents of the HTML. The replacement process
migrates all of the attributes / classes from the old element to the new one. See Creating
Widgets section below for more information.</p></li>
<li><p><code>templateUrl</code> - Same as <code>template</code> but the template is loaded from the specified URL. Because
the template loading is asynchronous the compilation/linking is suspended until the template
is loaded.</p></li>
<li><p><code>replace</code> - if set to <code>true</code> then the template will replace the current element, rather than
append the template to the element.</p></li>
<li><p><code>transclude</code> - compile the content of the element and make it available to the directive.
Typically used with <a href="api/ng.directive:ngTransclude"><code>ngTransclude</code></a>. The advantage of transclusion is that the linking function receives a
transclusion function which is pre-bound to the correct scope. In a typical setup the widget
creates an <code>isolate</code> scope, but the transclusion is not a child, but a sibling of the <code>isolate</code>
scope. This makes it possible for the widget to have private state, and the transclusion to
be bound to the parent (pre-<code>isolate</code>) scope.</p>
<ul><li><code>true</code> - transclude the content of the directive.</li>
<li><code>'element'</code> - transclude the whole element including any directives defined at lower priority.</li></ul></li>
<li><p><code>compile</code>: This is the compile function described in the section below.</p></li>
<li><p><code>link</code>: This is the link function described in the section below. This property is used only
if the <code>compile</code> property is not defined.</p></li>
</ul>
<h3>Compile function</h3>
<pre class="prettyprint linenums">
function compile(tElement, tAttrs, transclude) { ... }
</pre>
<p>The compile function deals with transforming the template DOM. Since most directives do not do
template transformation, it is not used often. Examples that require compile functions are
directives that transform template DOM, such as <a href="api/ng.directive:ngRepeat"><code>ngRepeat</code></a>, or load the contents
asynchronously, such as <a href="api/ng.directive:ngView"><code>ngView</code></a>. The
compile function takes the following arguments.</p>
<ul>
<li><p><code>tElement</code> - template element - The element where the directive has been declared. It is
safe to do template transformation on the element and child elements only.</p></li>
<li><p><code>tAttrs</code> - template attributes - Normalized list of attributes declared on this element shared
between all directive compile functions. See <a href="guide/directive#Attributes">Attributes</a>.</p></li>
<li><p><code>transclude</code> - A transclude linking function: <code>function(scope, cloneLinkingFn)</code>.</p></li>
</ul>
<p>NOTE: The template instance and the link instance may not be the same objects if the template has
been cloned. For this reason it is not safe in the compile function to do anything other than DOM
transformation that applies to all DOM clones. Specifically, DOM listener registration should be
done in a linking function rather than in a compile function.</p>
<p>A compile function can have a return value which can be either a function or an object.</p>
<ul>
<li><p>returning a function - is equivalent to registering the linking function via the <code>link</code> property
of the config object when the compile function is empty.</p></li>
<li><p>returning an object with function(s) registered via <code>pre</code> and <code>post</code> properties - allows you to
control when a linking function should be called during the linking phase. See info about
pre-linking and post-linking functions below.</p></li>
</ul>
<h3>Linking function</h3>
<pre class="prettyprint linenums">
function link(scope, iElement, iAttrs, controller) { ... }
</pre>
<p>The link function is responsible for registering DOM listeners as well as updating the DOM. It is
executed after the template has been cloned. This is where most of the directive logic will be
put.</p>
<ul>
<li><p><code>scope</code> - <a href="api/ng.$rootScope.Scope"><code>Scope</code></a> - The scope to be used by the
directive for registering <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a>.</p></li>
<li><p><code>iElement</code> - instance element - The element where the directive is to be used. It is safe to
manipulate the children of the element only in <code>postLink</code> function since the children have
already been linked.</p></li>
<li><p><code>iAttrs</code> - instance attributes - Normalized list of attributes declared on this element shared
between all directive linking functions. See <a href="guide/directive#Attributes">Attributes</a>.</p></li>
<li><p><code>controller</code> - a controller instance - A controller instance if at least one directive on the
element defines a controller. The controller is shared among all the directives, which allows
the directives to use the controllers as a communication channel.</p></li>
</ul>
<h4>Pre-linking function</h4>
<p>Executed before the child elements are linked. Not safe to do DOM transformation since the
compiler linking function will fail to locate the correct elements for linking.</p>
<h4>Post-linking function</h4>
<p>Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.</p>
<p><a name="Attributes"></a></p>
<h3>Attributes</h3>
<p>The <a href="api/ng.$compile.directive.Attributes"><code>Attributes</code></a> object - passed as a parameter in the
link() or compile() functions - is a way of accessing:</p>
<ul>
<li><p><em>normalized attribute names:</em> Since a directive such as 'ngBind' can be expressed in many ways
such as 'ng:bind', or 'x-ng-bind', the attributes object allows for normalized accessed to
the attributes.</p></li>
<li><p><em>directive inter-communication:</em> All directives share the same instance of the attributes
object which allows the directives to use the attributes object as inter directive
communication.</p></li>
<li><p><em>supports interpolation:</em> Interpolation attributes are assigned to the attribute object
allowing other directives to read the interpolated value.</p></li>
<li><p><em>observing interpolated attributes:</em> Use <code>$observe</code> to observe the value changes of attributes
that contain interpolation (e.g. <code>src="{{bar}}"</code>). Not only is this very efficient but it's also
the only way to easily get the actual value because during the linking phase the interpolation
hasn't been evaluated yet and so the value is at this time set to <code>undefined</code>.</p></li>
</ul>
<pre class="prettyprint linenums">
function linkingFn(scope, elm, attrs, ctrl) {
// get the attribute value
console.log(attrs.ngModel);
// change the attribute
attrs.$set('ngModel', 'new value');
// observe changes to interpolated attribute
attrs.$observe('ngModel', function(value) {
console.log('ngModel has changed value to ' + value);
});
}
</pre>
<h2>Understanding Transclusion and Scopes</h2>
<p>It is often desirable to have reusable components. Below is a pseudo code showing how a simplified
dialog component may work.</p>
<pre class="prettyprint linenums">
&lt;div&gt;
&lt;button ng-click="show=true"&gt;show&lt;/button&gt;
&lt;dialog title="Hello {{username}}."
visible="show"
on-cancel="show = false"
on-ok="show = false; doSomething()"&gt;
Body goes here: {{username}} is {{title}}.
&lt;/dialog&gt;
&lt;/div&gt;
</pre>
<p>Clicking on the "show" button will open the dialog. The dialog will have a title, which is
data bound to <code>username</code>, and it will also have a body which we would like to transclude
into the dialog.</p>
<p>Here is an example of what the template definition for the <code>dialog</code> widget may look like.</p>
<pre class="prettyprint linenums">
&lt;div ng-show="visible"&gt;
&lt;h3&gt;{{title}}&lt;/h3&gt;
&lt;div class="body" ng-transclude&gt;&lt;/div&gt;
&lt;div class="footer"&gt;
&lt;button ng-click="onOk()"&gt;Save changes&lt;/button&gt;
&lt;button ng-click="onCancel()"&gt;Close&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>This will not render properly, unless we do some scope magic.</p>
<p>The first issue we have to solve is that the dialog box template expects <code>title</code> to be defined, but
the place of instantiation would like to bind to <code>username</code>. Furthermore the buttons expect the
<code>onOk</code> and <code>onCancel</code> functions to be present in the scope. This limits the usefulness of the
widget. To solve the mapping issue we use the <code>locals</code> to create local variables which the template
expects as follows:</p>
<pre class="prettyprint linenums">
scope: {
title: '@', // the title uses the data-binding from the parent scope
onOk: '&', // create a delegate onOk function
onCancel: '&', // create a delegate onCancel function
visible: '=' // set up visible to accept data-binding
}
</pre>
<p>Creating local properties on widget scope creates two problems:</p>
<ol>
<li><p>isolation - if the user forgets to set <code>title</code> attribute of the dialog widget the dialog
template will bind to parent scope property. This is unpredictable and undesirable.</p></li>
<li><p>transclusion - the transcluded DOM can see the widget locals, which may overwrite the
properties which the transclusion needs for data-binding. In our example the <code>title</code>
property of the widget clobbers the <code>title</code> property of the transclusion.</p></li>
</ol>
<p>To solve the issue of lack of isolation, the directive declares a new <code>isolated</code> scope. An
isolated scope does not prototypically inherit from the child scope, and therefore we don't have
to worry about accidentally clobbering any properties.</p>
<p>However <code>isolated</code> scope creates a new problem: if a transcluded DOM is a child of the widget
isolated scope then it will not be able to bind to anything. For this reason the transcluded scope
is a child of the original scope, before the widget created an isolated scope for its local
variables. This makes the transcluded and widget isolated scope siblings.</p>
<p>This may seem to be unexpected complexity, but it gives the widget user and developer the least
surprise.</p>
<p>Therefore the final directive definition looks something like this:</p>
<pre class="prettyprint linenums">
transclude: true,
scope: {
title: '@', // the title uses the data-binding from the parent scope
onOk: '&', // create a delegate onOk function
onCancel: '&', // create a delegate onCancel function
visible: '=' // set up visible to accept data-binding
},
restrict: 'E',
replace: true
</pre>
<h2>Creating Components</h2>
<p>It is often desirable to replace a single directive with a more complex DOM structure. This
allows the directives to become a short hand for reusable components from which applications
can be built.</p>
<p>Following is an example of building a reusable widget.</p>
<h3>Source</h3>
<div source-edit="zippyModule" source-edit-deps="angular.js script.js" source-edit-html="index.html-48" source-edit-css="style.css-47" source-edit-js="script.js-46" source-edit-unit="" source-edit-scenario="scenario.js-49"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-48" ng-html-wrap="zippyModule angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-48">
<div ng-controller="Ctrl3">
Title: <input ng-model="title"> <br>
Text: <textarea ng-model="text"></textarea>
<hr>
<div class="zippy" zippy-title="Details: {{title}}...">{{text}}</div>
</div>
</script>
</div>
<div class="tab-pane" title="style.css">
<pre class="prettyprint linenums" ng-set-text="style.css-47"></pre>
<style type="text/css" id="style.css-47">
.zippy {
border: 1px solid black;
display: inline-block;
width: 250px;
}
.zippy.opened > .title:before { content: '▼ '; }
.zippy.opened > .body { display: block; }
.zippy.closed > .title:before { content: '► '; }
.zippy.closed > .body { display: none; }
.zippy > .title {
background-color: black;
color: white;
padding: .1em .3em;
cursor: pointer;
}
.zippy > .body {
padding: .1em .3em;
}
</style>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-46"></pre>
<script type="text/ng-template" id="script.js-46">
function Ctrl3($scope) {
$scope.title = 'Lorem Ipsum';
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}
angular.module('zippyModule', [])
.directive('zippy', function(){
return {
restrict: 'C',
// This HTML will replace the zippy directive.
replace: true,
transclude: true,
scope: { title:'@zippyTitle' },
template: '<div>' +
'<div class="title">{{title}}</div>' +
'<div class="body" ng-transclude></div>' +
'</div>',
// The linking function will add behavior to the template
link: function(scope, element, attrs) {
// Title element
var title = angular.element(element.children()[0]),
// Opened / closed state
opened = true;
// Clicking on title should open/close the zippy
title.bind('click', toggle);
// Toggle the closed/opened state
function toggle() {
opened = !opened;
element.removeClass(opened ? 'closed' : 'opened');
element.addClass(opened ? 'opened' : 'closed');
}
// initialize the zippy
toggle();
}
}
});
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-49"></pre>
<script type="text/ng-template" id="scenario.js-49">
it('should bind and open / close', function() {
input('title').enter('TITLE');
input('text').enter('TEXT');
expect(element('.title').text()).toEqual('Details: TITLE...');
expect(binding('text')).toEqual('TEXT');
expect(element('.zippy').prop('className')).toMatch(/closed/);
element('.zippy > .title').click();
expect(element('.zippy').prop('className')).toMatch(/opened/);
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="zippyModule" ng-set-html="index.html-48" ng-eval-javascript="script.js-46"></div></div>

View file

@ -0,0 +1,216 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Expressions are JavaScript-like code snippets that are usually placed in bindings such as <code>{{
expression }}</code>. Expressions are processed by <a href="api/ng.$parse"><code>$parse</code></a>
service.</p>
<p>For example, these are all valid expressions in angular:</p>
<ul>
<li><code>1+2</code></li>
<li><code>3*10 | currency</code></li>
<li><code>user.name</code></li>
</ul>
<h3>Angular Expressions vs. JS Expressions</h3>
<p>It might be tempting to think of Angular view expressions as JavaScript expressions, but that is
not entirely correct, since Angular does not use a JavaScript <code>eval()</code> to evaluate expressions.
You can think of Angular expressions as JavaScript expressions with following differences:</p>
<ul>
<li><p><strong>Attribute Evaluation:</strong> evaluation of all properties are against the scope, doing the
evaluation, unlike in JavaScript where the expressions are evaluated against the global
<code>window</code>.</p></li>
<li><p><strong>Forgiving:</strong> expression evaluation is forgiving to undefined and null, unlike in JavaScript,
where such evaluations generate <code>NullPointerExceptions</code>.</p></li>
<li><p><strong>No Control Flow Statements:</strong> you cannot do any of the following in angular expression:
conditionals, loops, or throw.</p></li>
<li><p><strong>Filters:</strong> you can pass result of expression evaluations through filter chains. For example
to convert date object into a local specific human-readable format.</p></li>
</ul>
<p>If, on the other hand, you do want to run arbitrary JavaScript code, you should make it a
controller method and call the method. If you want to <code>eval()</code> an angular expression from
JavaScript, use the <a href="api/ng.$rootScope.Scope#$eval"><code><code>$eval()</code></code></a> method.</p>
<h3>Example</h3>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js" source-edit-html="index.html-50" source-edit-css="" source-edit-js="" source-edit-unit="" source-edit-scenario="scenario.js-51"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-50" ng-html-wrap=" angular.js"></pre>
<script type="text/ng-template" id="index.html-50">
1+2={{1+2}}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-51"></pre>
<script type="text/ng-template" id="scenario.js-51">
it('should calculate expression in binding', function() {
expect(binding('1+2')).toEqual('3');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-50" ng-eval-javascript=""></div>
<p>You can try evaluating different expressions here:</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-53" source-edit-css="" source-edit-js="script.js-52" source-edit-unit="" source-edit-scenario="scenario.js-54"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-53" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-53">
<div ng-controller="Cntl2" class="expressions">
Expression:
<input type='text' ng-model="expr" size="80"/>
<button ng-click="addExp(expr)">Evaluate</button>
<ul>
<li ng-repeat="expr in exprs">
[ <a href="" ng-click="removeExp($index)">X</a> ]
<tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
</li>
</ul>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-52"></pre>
<script type="text/ng-template" id="script.js-52">
function Cntl2($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-54"></pre>
<script type="text/ng-template" id="scenario.js-54">
it('should allow user expression testing', function() {
element('.expressions :button').click();
var li = using('.expressions ul').repeater('li');
expect(li.count()).toBe(1);
expect(li.row(0)).toEqual(["3*10|currency", "$30.00"]);
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-53" ng-eval-javascript="script.js-52"></div>
<h2>Property Evaluation</h2>
<p>Evaluation of all properties takes place against a scope. Unlike JavaScript, where names default
to global window properties, Angular expressions have to use <a href="api/ng.$window"><code><code>$window</code></code></a> to refer to the global <code>window</code> object. For example, if you want to call <code>alert()</code>, which is
defined on <code>window</code>, in an expression you must use <code>$window.alert()</code>. This is done intentionally to
prevent accidental access to the global state (a common source of subtle bugs).</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-56" source-edit-css="" source-edit-js="script.js-55" source-edit-unit="" source-edit-scenario="scenario.js-57"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-56" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-56">
<div class="example2" ng-controller="Cntl1">
Name: <input ng-model="name" type="text"/>
<button ng-click="greet()">Greet</button>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-55"></pre>
<script type="text/ng-template" id="script.js-55">
function Cntl1($window, $scope){
$scope.name = 'World';
$scope.greet = function() {
($window.mockWindow || $window).alert('Hello ' + $scope.name);
}
}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-57"></pre>
<script type="text/ng-template" id="scenario.js-57">
it('should calculate expression in binding', function() {
var alertText;
this.addFutureAction('set mock', function($window, $document, done) {
$window.mockWindow = {
alert: function(text){ alertText = text; }
};
done();
});
element(':button:contains(Greet)').click();
expect(this.addFuture('alert text', function(done) {
done(null, alertText);
})).toBe('Hello World');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-56" ng-eval-javascript="script.js-55"></div>
<h3>Forgiving</h3>
<p>Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating <code>a.b.c</code> throws
an exception if <code>a</code> is not an object. While this makes sense for a general purpose language, the
expression evaluations are primarily used for data binding, which often look like this:</p>
<pre><code> {{a.b.c}}
</code></pre>
<p>It makes more sense to show nothing than to throw an exception if <code>a</code> is undefined (perhaps we are
waiting for the server response, and it will become defined soon). If expression evaluation wasn't
forgiving we'd have to write bindings that clutter the code, for example: <code>{{((a||{}).b||{}).c}}</code></p>
<p>Similarly, invoking a function <code>a.b.c()</code> on undefined or null simply returns undefined.</p>
<h3>No Control Flow Statements</h3>
<p>You cannot write a control flow statement in an expression. The reason behind this is core to the
Angular philosophy that application logic should be in controllers, not in the view. If you need a
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.</p>
<h3>Filters</h3>
<p>When presenting data to the user, you might need to convert the data from its raw format to a
user-friendly format. For example, you might have a data object that needs to be formatted
according to the locale before displaying it to the user. You can pass expressions through a chain
of filters like this:</p>
<pre><code> name | uppercase
</code></pre>
<p>The expression evaluator simply passes the value of name to <a href="api/ng.filter:uppercase"><code><code>uppercase</code></code></a> filter.</p>
<p>Chain filters using this syntax:</p>
<pre><code> value | filter1 | filter2
</code></pre>
<p>You can also pass colon-delimited arguments to filters, for example, to display the number 123
with 2 decimal points:</p>
<pre><code> 123 | number:2
</code></pre>
<h2>The $</h2>
<p>You might be wondering, what is the significance of the $ prefix? It is simply a prefix that
angular uses, to differentiate its API names from others. If angular didn't use $, then evaluating
<code>a.length()</code> would return undefined because neither a nor angular define such a property.</p>
<p>Consider that in a future version of Angular we might choose to add a length method, in which case
the behavior of the expression would change. Worse yet, you the developer could create a length
property and then we would have a collision. This problem exists because Angular augments existing
objects with additional behavior. By prefixing its additions with $ we are reserving our namespace
so that angular developers and developers who use Angular can develop in harmony without collisions.</p></div>

View file

@ -0,0 +1,368 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Controls (<code>input</code>, <code>select</code>, <code>textarea</code>) are a way for user to enter data.
Form is a collection of controls for the purpose of grouping related controls together.</p>
<p>Form and controls provide validation services, so that the user can be notified of invalid input.
This provides a better user experience, because the user gets instant feedback on how to correct the error.
Keep in mind that while client-side validation plays an important role in providing good user experience, it can easily be circumvented and thus can not be trusted.
Server-side validation is still necessary for a secure application.</p>
<h2>Simple form</h2>
<p>The key directive in understanding two-way data-binding is <a href="api/ng.directive:ngModel"><code>ngModel</code></a>.
The <code>ngModel</code> directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
In addition it provides an <a href="api/ng.directive:ngModel.NgModelController"><code>API</code></a> for other directives to augment its behavior.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-59" source-edit-css="" source-edit-js="script.js-58" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-59" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-59">
<div ng-controller="Controller">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
<pre>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-58"></pre>
<script type="text/ng-template" id="script.js-58">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-59" ng-eval-javascript="script.js-58"></div>
<p>Note that <code>novalidate</code> is used to disable browser's native form validation.</p>
<h2>Using CSS classes</h2>
<p>To allow styling of form as well as controls, <code>ngModel</code> add these CSS classes:</p>
<ul>
<li><code>ng-valid</code></li>
<li><code>ng-invalid</code></li>
<li><code>ng-pristine</code></li>
<li><code>ng-dirty</code></li>
</ul>
<p>The following example uses the CSS to display validity of each form control.
In the example both <code>user.name</code> and <code>user.email</code> are required, but are rendered with red background only when they are dirty.
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-61" source-edit-css="" source-edit-js="script.js-60" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-61" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-61">
<div ng-controller="Controller">
<form novalidate class="css-form">
Name:
<input type="text" ng-model="user.name" required /><br />
E-mail: <input type="email" ng-model="user.email" required /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
</div>
<style type="text/css">
.css-form input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
.css-form input.ng-valid.ng-dirty {
background-color: #78FA89;
}
</style>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-60"></pre>
<script type="text/ng-template" id="script.js-60">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-61" ng-eval-javascript="script.js-60"></div>
<h2>Binding to form and control state</h2>
<p>A form is in instance of <a href="api/ng.directive:form.FormController"><code>FormController</code></a>.
The form instance can optionally be published into the scope using the <code>name</code> attribute.
Similarly control is an instance of <a href="api/ng.directive:ngModel.NgModelController"><code>NgModelController</code></a>.
The control instance can similarly be published into the form instance using the <code>name</code> attribute.
This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.</p>
<p>This allows us to extend the above example with these features:</p>
<ul>
<li>RESET button is enabled only if form has some changes</li>
<li>SAVE button is enabled only if form has some changes and is valid</li>
<li>custom error messages for <code>user.email</code> and <code>user.agree</code></li>
</ul>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-63" source-edit-css="" source-edit-js="script.js-62" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-63" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-63">
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br />
E-mail:
<input type="email" ng-model="user.email" name="uEmail" required/><br />
<div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
<span ng-show="form.uEmail.$error.required">Tell us your email.</span>
<span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<input type="checkbox" ng-model="user.agree" name="userAgree" required />
I agree: <input ng-show="user.agree" type="text" ng-model="user.agreeSign"
required /><br />
<div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
<button ng-click="reset()" ng-disabled="isUnchanged(user)">RESET</button>
<button ng-click="update(user)"
ng-disabled="form.$invalid || isUnchanged(user)">SAVE</button>
</form>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-62"></pre>
<script type="text/ng-template" id="script.js-62">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-63" ng-eval-javascript="script.js-62"></div>
<h2>Custom Validation</h2>
<p>Angular provides basic implementation for most common html5 <a href="api/ng.directive:input"><code>input</code></a>
types: (<a href="api/ng.directive:input.text"><code>text</code></a>, <a href="api/ng.directive:input.number"><code>number</code></a>, <a href="api/ng.directive:input.url"><code>url</code></a>, <a href="api/ng.directive:input.email"><code>email</code></a>, <a href="api/ng.directive:input.radio"><code>radio</code></a>, <a href="api/ng.directive:input.checkbox"><code>checkbox</code></a>), as well as some directives for validation (<code>required</code>, <code>pattern</code>, <code>minlength</code>, <code>maxlength</code>, <code>min</code>, <code>max</code>).</p>
<p>Defining your own validator can be done by defining your own directive which adds a custom validation function to the <code>ngModel</code> <a href="api/ng.directive:ngModel.NgModelController"><code>controller</code></a>.
To get a hold of the controller the directive specifies a dependency as shown in the example below.
The validation can occur in two places:</p>
<ul>
<li><p><strong>Model to View update</strong> -
Whenever the bound model changes, all functions in <a href="api/ng.directive:ngModel.NgModelController#$formatters"><code>NgModelController#$formatters</code></a> array are pipe-lined, so that each of these functions has an opportunity to format the value and change validity state of the form control through <a href="api/ng.directive:ngModel.NgModelController#$setValidity"><code>NgModelController#$setValidity</code></a>.</p></li>
<li><p><strong>View to Model update</strong> -
In a similar way, whenever a user interacts with a control it calls <a href="api/ng.directive:ngModel.NgModelController#$setViewValue"><code>NgModelController#$setViewValue</code></a>.
This in turn pipelines all functions in the <a href="api/ng.directive:ngModel.NgModelController#$parsers"><code>NgModelController#$parsers</code></a> array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through <a href="api/ng.directive:ngModel.NgModelController#$setValidity"><code>NgModelController#$setValidity</code></a>.</p></li>
</ul>
<p>In the following example we create two directives.</p>
<ul>
<li><p>The first one is <code>integer</code> and it validates whether the input is a valid integer.
For example <code>1.23</code> is an invalid value, since it contains a fraction.
Note that we unshift the array instead of pushing.
This is because we want to be first parser and consume the control string value, as we need to execute the validation function before a conversion to number occurs.</p></li>
<li><p>The second directive is a <code>smart-float</code>.
It parses both <code>1.2</code> and <code>1,2</code> into a valid float number <code>1.2</code>.
Note that we can't use input type <code>number</code> here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as <code>1,2</code>.</p></li>
</ul>
<h3>Source</h3>
<div source-edit="form-example1" source-edit-deps="angular.js script.js" source-edit-html="index.html-65" source-edit-css="" source-edit-js="script.js-64" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-65" ng-html-wrap="form-example1 angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-65">
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
<div>
Size (integer 0 - 10):
<input type="number" ng-model="size" name="size"
min="0" max="10" integer />{{size}}<br />
<span ng-show="form.size.$error.integer">This is not valid integer!</span>
<span ng-show="form.size.$error.min || form.size.$error.max">
The value must be in range 0 to 10!</span>
</div>
<div>
Length (float):
<input type="text" ng-model="length" name="length" smart-float />
{{length}}<br />
<span ng-show="form.length.$error.float">
This is not a valid float number!</span>
</div>
</form>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-64"></pre>
<script type="text/ng-template" id="script.js-64">
var app = angular.module('form-example1', []);
var INTEGER_REGEXP = /^\-?\d*$/;
app.directive('integer', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (INTEGER_REGEXP.test(viewValue)) {
// it is valid
ctrl.$setValidity('integer', true);
return viewValue;
} else {
// it is invalid, return undefined (no model update)
ctrl.$setValidity('integer', false);
return undefined;
}
});
}
};
});
var FLOAT_REGEXP = /^\-?\d+((\.|\,)\d+)?$/;
app.directive('smartFloat', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (FLOAT_REGEXP.test(viewValue)) {
ctrl.$setValidity('float', true);
return parseFloat(viewValue.replace(',', '.'));
} else {
ctrl.$setValidity('float', false);
return undefined;
}
});
}
};
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="form-example1" ng-set-html="index.html-65" ng-eval-javascript="script.js-64"></div>
<h2>Implementing custom form controls (using <code>ngModel</code>)</h2>
<p>Angular implements all of the basic HTML form controls (<a href="api/ng.directive:input"><code>input</code></a>, <a href="api/ng.directive:select"><code>select</code></a>, <a href="api/ng.directive:textarea"><code>textarea</code></a>), which should be sufficient for most cases.
However, if you need more flexibility, you can write your own form control as a directive.</p>
<p>In order for custom control to work with <code>ngModel</code> and to achieve two-way data-binding it needs to:</p>
<ul>
<li>implement <code>render</code> method, which is responsible for rendering the data after it passed the <a href="api/ng.directive:ngModel.NgModelController#$formatters"><code>NgModelController#$formatters</code></a>,</li>
<li>call <code>$setViewValue</code> method, whenever the user interacts with the control and model needs to be updated. This is usually done inside a DOM Event listener.</li>
</ul>
<p>See <a href="guide/directive">$compileProvider.directive</a> for more info.</p>
<p>The following example shows how to add two-way data-binding to contentEditable elements.</p>
<h3>Source</h3>
<div source-edit="form-example2" source-edit-deps="angular.js script.js" source-edit-html="index.html-67" source-edit-css="" source-edit-js="script.js-66" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-67" ng-html-wrap="form-example2 angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-67">
<div contentEditable="true" ng-model="content" title="Click to edit">Some</div>
<pre>model = {{content}}</pre>
<style type="text/css">
div[contentEditable] {
cursor: pointer;
background-color: #D0D0D0;
}
</style>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-66"></pre>
<script type="text/ng-template" id="script.js-66">
angular.module('form-example2', []).directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
});
// model -> view
ctrl.$render = function() {
elm.html(ctrl.$viewValue);
};
// load init value from DOM
ctrl.$setViewValue(elm.html());
}
};
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="form-example2" ng-set-html="index.html-67" ng-eval-javascript="script.js-66"></div></div>

View file

@ -0,0 +1,113 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>I18n and L10n in AngularJS</h2>
<p><strong>What is i18n and l10n?</strong></p>
<p>Internationalization, abbreviated i18n, is the process of developing products in such a way that
they can be localized for languages and cultures easily. Localization, abbreviated l10n, is the
process of adapting applications and text to enable their usability in a particular cultural or
linguistic market. For application developers, internationalizing an application means abstracting
all of the strings and other locale-specific bits (such as date or currency formats) out of the
application. Localizing an application means providing translations and localized formats for the
abstracted bits.</p>
<p><strong>What level of support for i18n/l10n is currently in Angular?</strong></p>
<p>Currently, Angular supports i18n/l10n for <a href="http://docs.angularjs.org/#!/api/ng.filter:date">datetime</a>, <a href="http://docs.angularjs.org/#!/api/ng.filter:number">number</a> and <a href="http://docs.angularjs.org/#!/api/ng.filter:currency">currency</a> filters.</p>
<p>Additionally, Angular supports localizable pluralization support provided by the <a href="api/ng.directive:ngPluralize"><code>ngPluralize directive</code></a>.</p>
<p>All localizable Angular components depend on locale-specific rule sets managed by the <a href="api/ng.$locale"><code>$locale service</code></a>.</p>
<p>For readers who want to jump straight into examples, we have a few web pages that showcase how to
use Angular filters with various locale rule sets. You can find these examples either on <a href="https://github.com/angular/angular.js/tree/master/i18n/e2e">Github</a> or in the i18n/e2e folder of
Angular development package.</p>
<p><strong>What is a locale id?</strong></p>
<p>A locale is a specific geographical, political, or cultural region. The most commonly used locale
ID consists of two parts: language code and country code. For example, en-US, en-AU, zh-CN are all
valid locale IDs that have both language codes and country codes. Because specifying a country code
in locale ID is optional, locale IDs such as en, zh, and sk are also valid. See the <a href="http://userguide.icu-project.org/locale">ICU</a> website for more information about using locale IDs.</p>
<p><strong>Supported locales in Angular</strong>
Angular separates number and datetime format rule sets into different files, each file for a
particular locale. You can find a list of currently supported locales <a href="https://github.com/angular/angular.js/tree/master/i18n/locale">here</a></p>
<h2>Providing locale rules to Angular</h2>
<p>There are two approaches to providing locale rules to Angular:</p>
<p><strong>1. Pre-bundled rule sets</strong></p>
<p>You can pre-bundle the desired locale file with Angular by concatenating the content of the
locale-specific file to the end of <code>angular.js</code> or <code>angular.min.js</code> file.</p>
<p>For example on *nix, to create a an angular.js file that contains localization rules for german
locale, you can do the following:</p>
<p><code>cat angular.js i18n/angular-locale_de-ge.js &gt; angular_de-ge.js</code></p>
<p>When the application containing <code>angular_de-ge.js</code> script instead of the generic angular.js script
starts, Angular is automatically pre-configured with localization rules for the german locale.</p>
<p><strong>2. Including locale js script in index.html page</strong></p>
<p>You can also include the locale specific js file in the index.html page. For example, if one client
requires German locale, you would serve index_de-ge.html which will look something like this:</p>
<pre class="prettyprint linenums">
&lt;html ng-app&gt;
&lt;head&gt;
….
&lt;script src="angular.js"&gt;&lt;/script&gt;
&lt;script src="i18n/angular-locale_de-ge.js"&gt;&lt;/script&gt;
….
&lt;/head&gt;
&lt;/html&gt;
</pre>
<p><strong>Comparison of the two approaches</strong>
Both approaches described above requires you to prepare different index.html pages or js files for
each locale that your app may be localized into. You also need to configure your server to serve
the correct file that correspond to the desired locale.</p>
<p>However, the second approach (Including locale js script in index.html page) is likely to be slower
because an extra script needs to be loaded.</p>
<h2>"Gotchas"</h2>
<p><strong>Currency symbol "gotcha"</strong></p>
<p>Angular's <a href="http://docs.angularjs.org/#!/api/ng.filter:currency">currency filter</a> allows
you to use the default currency symbol from the <a href="api/ng.$locale"><code>locale service</code></a>,
or you can provide the filter with a custom currency symbol. If your app will be used only in one
locale, it is fine to rely on the default currency symbol. However, if you anticipate that viewers
in other locales might use your app, you should provide your own currency symbol to make sure the
actual value is understood.</p>
<p>For example, if you want to display account balance of 1000 dollars with the following binding
containing currency filter: <code>{{ 1000 | currency }}</code>, and your app is currently in en-US locale.
'$1000.00' will be shown. However, if someone in a different local (say, Japan) views your app, her
browser will specify the locale as ja, and the balance of '¥1000.00' will be shown instead. This
will really upset your client.</p>
<p>In this case, you need to override the default currency symbol by providing the <a href="http://docs.angularjs.org/#!/api/ng.filter:currency">currency filter</a> with a currency symbol as
a parameter when you configure the filter, for example, {{ 1000 | currency:"USD$"}}. This way,
Angular will always show a balance of 'USD$1000' and disregard any locale changes.</p>
<p><strong>Translation length "gotcha"</strong></p>
<p>Keep in mind that translated strings/datetime formats can vary greatly in length. For example,
<code>June 3, 1977</code> will be translated to Spanish as <code>3 de junio de 1977</code>. There are bound to be other
more extreme cases. Hence, when internationalizing your apps, you need to apply CSS rules
accordingly and do thorough testing to make sure UI components do not overlap.</p>
<p><strong>Timezones</strong></p>
<p>Keep in mind that Angular datetime filter uses the time zone settings of the browser. So the same
application will show different time information depending on the time zone settings of the
computer that the application is running on. Neither Javascript nor Angular currently supports
displaying the date with a timezone specified by the developer.</p></div>

View file

@ -0,0 +1,160 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>Overview</h2>
<p>This document describes the Internet Explorer (IE) idiosyncrasies when dealing with custom HTML
attributes and tags. Read this document if you are planning on deploying your Angular application
on IE v8.0 or earlier.</p>
<h2>Short Version</h2>
<p>To make your Angular application work on IE please make sure that:</p>
<ol>
<li><p>You polyfill JSON.stringify if necessary (IE7 will need this). You can use
<a href="https://github.com/douglascrockford/JSON-js">JSON2</a> or
<a href="http://bestiejs.github.com/json3/">JSON3</a> polyfills for this.</p></li>
<li><p>you <strong>do not</strong> use custom element tags such as <code>&lt;ng:view&gt;</code> (use the attribute version
<code>&lt;div ng-view&gt;</code> instead), or</p></li>
<li><p>if you <strong>do use</strong> custom element tags, then you must take these steps to make IE happy:</p></li>
</ol>
<pre class="prettyprint linenums">
&lt;html xmlns:ng="http://angularjs.org"&gt;
&lt;head&gt;
&lt;!--[if lte IE 8]&gt;
&lt;script&gt;
document.createElement('ng-include');
document.createElement('ng-pluralize');
document.createElement('ng-view');
// Optionally these for CSS
document.createElement('ng:include');
document.createElement('ng:pluralize');
document.createElement('ng:view');
&lt;/script&gt;
&lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
...
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The <strong>important</strong> parts are:</p>
<ul>
<li><p><code>xmlns:ng</code> - <em>namespace</em> - you need one namespace for each custom tag you are planning on
using.</p></li>
<li><p><code>document.createElement(yourTagName)</code> - <em>creation of custom tag names</em> - Since this is an
issue only for older version of IE you need to load it conditionally. For each tag which does
not have namespace and which is not defined in HTML you need to pre-declare it to make IE
happy.</p></li>
</ul>
<h2>Long Version</h2>
<p>IE has issues with element tag names which are not standard HTML tag names. These fall into two
categories, and each category has its own fix.</p>
<ul>
<li><p>If the tag name starts with <code>my:</code> prefix than it is considered an XML namespace and must
have corresponding namespace declaration on <code>&lt;html xmlns:my="ignored"&gt;</code></p></li>
<li><p>If the tag has no <code>:</code> but it is not a standard HTML tag, then it must be pre-created using
<code>document.createElement('my-tag')</code></p></li>
<li><p>If you are planning on styling the custom tag with CSS selectors, then it must be
pre-created using <code>document.createElement('my-tag')</code> regardless of XML namespace.</p></li>
</ul>
<h3>The Good News</h3>
<p>The good news is that these restrictions only apply to element tag names, and not to element
attribute names. So this requires no special handling in IE: <code>&lt;div my-tag your:tag&gt;
&lt;/div&gt;</code>.</p>
<h3>What happens if I fail to do this?</h3>
<p>Suppose you have HTML with unknown tag <code>mytag</code> (this could also be <code>my:tag</code> or <code>my-tag</code> with same
result):</p>
<pre class="prettyprint linenums">
&lt;html&gt;
&lt;body&gt;
&lt;mytag&gt;some text&lt;/mytag&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>It should parse into the following DOM:</p>
<pre class="prettyprint linenums">
#document
+- HTML
+- BODY
+- mytag
+- #text: some text
</pre>
<p>The expected behavior is that the <code>BODY</code> element has a child element <code>mytag</code>, which in turn has
the text <code>some text</code>.</p>
<p>But this is not what IE does (if the above fixes are not included):</p>
<pre class="prettyprint linenums">
#document
+- HTML
+- BODY
+- mytag
+- #text: some text
+- /mytag
</pre>
<p>In IE, the behavior is that the <code>BODY</code> element has three children:</p>
<ol>
<li><p>A self closing <code>mytag</code>. Example of self closing tag is <code>&lt;br/&gt;</code>. The trailing <code>/</code> is optional,
but the <code>&lt;br&gt;</code> tag is not allowed to have any children, and browsers consider <code>&lt;br&gt;some
text&lt;/br&gt;</code> as three siblings not a <code>&lt;br&gt;</code> with <code>some text</code> as child.</p></li>
<li><p>A text node with <code>some text</code>. This should have been a child of <code>mytag</code> above, not a sibling.</p></li>
<li><p>A corrupt self closing <code>/mytag</code>. This is corrupt since element names are not allowed to have
the <code>/</code> character. Furthermore this closing element should not be part of the DOM since it is
only used to delineate the structure of the DOM.</p></li>
</ol>
<h3>CSS Styling of Custom Tag Names</h3>
<p>To make CSS selectors work with custom elements, the custom element name must be pre-created with
<code>document.createElement('my-tag')</code> regardless of XML namespace.</p>
<pre class="prettyprint linenums">
&lt;html xmlns:ng="needed for ng: namespace"&gt;
&lt;head&gt;
&lt;!--[if lte IE 8]&gt;
&lt;script&gt;
// needed to make ng-include parse properly
document.createElement('ng-include');
// needed to enable CSS reference
document.createElement('ng:view');
&lt;/script&gt;
&lt;![endif]--&gt;
&lt;style&gt;
ng\\:view {
display: block;
border: 1px solid red;
}
ng-include {
display: block;
border: 1px solid blue;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;ng:view&gt;&lt;/ng:view&gt;
&lt;ng-include&gt;&lt;/ng-include&gt;
...
&lt;/body&gt;
&lt;/html&gt;
</pre></div>

View file

@ -0,0 +1,13 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Welcome to the angular Developer Guide. If you are here to learn the details of how to use angular
to develop web apps, you've come to the right place.</p>
<p>If you are completely or relatively unfamiliar with angular, you may want to check out one or both
of the following documents before returning here to the Developer Guide:</p>
<ul>
<li><a href="misc/started">Getting Started</a></li>
<li><a href="tutorial/index">Angular Tutorial</a></li>
</ul></div>

View file

@ -0,0 +1,45 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><p>Angular is pure client-side technology, written entirely in JavaScript. It works with the
long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of
web apps easier and faster than ever before.</p>
<p>One important way that Angular simplifies web development is by increasing the level of abstraction
between the developer and most low-level web app development tasks. Angular automatically takes
care of many of these tasks, including:</p>
<ul>
<li>DOM Manipulation</li>
<li>Setting Up Listeners and Notifiers</li>
<li>Input Validation</li>
</ul>
<p>Because Angular handles much of the work involved in these tasks, developers can concentrate more
on application logic and less on repetitive, error-prone, lower-level coding.</p>
<p>At the same time that Angular simplifies the development of web apps, it brings relatively
sophisticated techniques to the client-side, including:</p>
<ul>
<li>Separation of data, application logic, and presentation components</li>
<li>Data Binding between data and presentation components</li>
<li>Services (common web app operations, implemented as substitutable objects)</li>
<li>Dependency Injection (used primarily for wiring together services)</li>
<li>An extensible HTML compiler (written entirely in JavaScript)</li>
<li>Ease of Testing</li>
</ul>
<p>These techniques have been for the most part absent from the client-side for far too long.</p>
<h3>Single-page / Round-trip Applications</h3>
<p>You can use Angular to develop both single-page and round-trip apps, but Angular is designed
primarily for developing single-page apps. Angular supports browser history, forward and back
buttons, and bookmarking in single-page apps.</p>
<p>You normally wouldn't want to load Angular with every page change, as would be the case with using
Angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
Angular's features (for example, templates to leverage angular's data-binding feature) to an
existing round-trip app. You might follow this course of action if you were migrating an older app
to a single-page Angular app.</p></div>

View file

@ -0,0 +1,276 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>What is a Module?</h2>
<p>Most applications have a main method which instantiates, wires, and bootstraps the application.
Angular apps don't have a main method. Instead modules declaratively specify how an application
should be bootstrapped. There are several advantages to this approach:</p>
<ul>
<li>The process is more declarative which is easier to understand</li>
<li>In unit-testing there is no need to load all modules, which may aid in writing unit-tests.</li>
<li>Additional modules can be loaded in scenario tests, which can override some of the
configuration and help end-to-end test the application</li>
<li>Third party code can be packaged as reusable modules.</li>
<li>The modules can be loaded in any/parallel order (due to delayed nature of module execution).</li>
</ul>
<h2>The Basics</h2>
<p>Ok, I'm in a hurry. How do I get a Hello World module working?</p>
<p>Important things to notice:</p>
<ul>
<li><a href="api/angular.Module"><code>Module</code></a> API</li>
<li>Notice the reference to the <code>myApp</code> module in the <code>&lt;html ng-app="myApp"&gt;</code>, it is what
bootstraps the app using your module.</li>
</ul>
<h3>Source</h3>
<div source-edit="myApp" source-edit-deps="angular.js script.js" source-edit-html="index.html-69" source-edit-css="" source-edit-js="script.js-68" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-69" ng-html-wrap="myApp angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-69">
<div>
{{ 'World' | greet }}
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-68"></pre>
<script type="text/ng-template" id="script.js-68">
// declare a module
var myAppModule = angular.module('myApp', []);
// configure the module.
// in this example we will create a greeting filter
myAppModule.filter('greet', function() {
return function(name) {
return 'Hello, ' + name + '!';
};
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="myApp" ng-set-html="index.html-69" ng-eval-javascript="script.js-68"></div>
<h2>Recommended Setup</h2>
<p>While the example above is simple, it will not scale to large applications. Instead we recommend
that you break your application to multiple modules like this:</p>
<ul>
<li>A service module, for service declaration</li>
<li>A directive module, for directive declaration</li>
<li>A filter module, for filter declaration</li>
<li>And an application level module which depends on the above modules, and which has
initialization code.</li>
</ul>
<p>The reason for this breakup is that in your tests, it is often necessary to ignore the
initialization code, which tends to be difficult to test. By putting it into a separate module it
can be easily ignored in tests. The tests can also be more focused by only loading the modules
that are relevant to tests.</p>
<p>The above is only a suggestion, so feel free to tailor it to your needs.</p>
<h3>Source</h3>
<div source-edit="xmpl" source-edit-deps="angular.js script.js" source-edit-html="index.html-71" source-edit-css="" source-edit-js="script.js-70" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-71" ng-html-wrap="xmpl angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-71">
<div ng-controller="XmplController">
{{ greeting }}!
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-70"></pre>
<script type="text/ng-template" id="script.js-70">
angular.module('xmpl.service', []).
value('greeter', {
salutation: 'Hello',
localize: function(localization) {
this.salutation = localization.salutation;
},
greet: function(name) {
return this.salutation + ' ' + name + '!';
}
}).
value('user', {
load: function(name) {
this.name = name;
}
});
angular.module('xmpl.directive', []);
angular.module('xmpl.filter', []);
angular.module('xmpl', ['xmpl.service', 'xmpl.directive', 'xmpl.filter']).
run(function(greeter, user) {
// This is effectively part of the main method initialization code
greeter.localize({
salutation: 'Bonjour'
});
user.load('World');
})
// A Controller for your app
var XmplController = function($scope, greeter, user) {
$scope.greeting = greeter.greet(user.name);
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="xmpl" ng-set-html="index.html-71" ng-eval-javascript="script.js-70"></div>
<h2>Module Loading &amp; Dependencies</h2>
<p>A module is a collection of configuration and run blocks which get applied to the application
during the bootstrap process. In its simplest form the module consist of collection of two kinds
of blocks:</p>
<ol>
<li><strong>Configuration blocks</strong> - get executed during the provider registrations and configuration
phase. Only providers and constants can be injected into configuration blocks. This is to
prevent accidental instantiation of services before they have been fully configured.</li>
<li><strong>Run blocks</strong> - get executed after the injector is created and are used to kickstart the
application. Only instances and constants can be injected into run blocks. This is to prevent
further system configuration during application run time.</li>
</ol>
<pre class="prettyprint linenums">
angular.module('myModule', []).
config(function(injectables) { // provider-injector
// This is an example of config block.
// You can have as many of these as you want.
// You can only inject Providers (not instances)
// into the config blocks.
}).
run(function(injectables) { // instance-injector
// This is an example of a run block.
// You can have as many of these as you want.
// You can only inject instances (not Providers)
// into the run blocks
});
</pre>
<h3>Configuration Blocks</h3>
<p>There are some convenience methods on the module which are equivalent to the config block. For
example:</p>
<pre class="prettyprint linenums">
angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);
// is same as
angular.module('myModule', []).
config(function($provide, $compileProvider, $filterProvider) {
$provide.value('a', 123)
$provide.factory('a', function() { return 123; })
$compileProvider.directive('directiveName', ...).
$filterProvider.register('filterName', ...);
});
</pre>
<p>The configuration blocks get applied in the order in which they are registered. The only exception
to it are constant definitions, which are placed at the beginning of all configuration blocks.</p>
<h3>Run Blocks</h3>
<p>Run blocks are the closest thing in Angular to the main method. A run block is the code which
needs to run to kickstart the application. It is executed after all of the service have been
configured and the injector has been created. Run blocks typically contain code which is hard
to unit-test, and for this reason should be declared in isolated modules, so that they can be
ignored in the unit-tests.</p>
<h3>Dependencies</h3>
<p>Modules can list other modules as their dependencies. Depending on a module implies that required
module needs to be loaded before the requiring module is loaded. In other words the configuration
blocks of the required modules execute before the configuration blocks or the requiring module.
The same is true for the run blocks. Each module can only be loaded once, even if multiple other
modules require it.</p>
<h3>Asynchronous Loading</h3>
<p>Modules are a way of managing $injector configuration, and have nothing to do with loading of
scripts into a VM. There are existing projects which deal with script loading, which may be used
with Angular. Because modules do nothing at load time they can be loaded into the VM in any order
and thus script loaders can take advantage of this property and parallelize the loading process.</p>
<h2>Unit Testing</h2>
<p>In its simplest form a unit test is a way of instantiating a subset of the application in test and
then applying a stimulus to it. It is important to realize that each module can only be loaded
once per injector. Typically an app has only one injector. But in tests, each test has its own
injector, which means that the modules are loaded multiple times per VM. Properly structured
modules can help with unit testing, as in this example:</p>
<p>In all of these examples we are going to assume this module definition:
<pre class="prettyprint linenums">
angular.module('greetMod', []).
factory('alert', function($window) {
return function(text) {
$window.alert(text);
}
}).
value('salutation', 'Hello').
factory('greet', function(alert, salutation) {
return function(name) {
alert(salutation + ' ' + name + '!');
}
});
</pre>
<p>Let's write some tests:
<pre class="prettyprint linenums">
describe('myApp', function() {
// load the relevant application modules then load a special
// test module which overrides the $window with a mock version,
// so that calling window.alert() will not block the test
// runner with a real alert box. This is an example of overriding
// configuration information in tests.
beforeEach(module('greetMod', function($provide) {
$provide.value('$window', {
alert: jasmine.createSpy('alert')
});
}));
// The inject() will create the injector and inject the greet and
// $window into the tests. The test need not concern itself with
// wiring of the application, only with testing it.
it('should alert on $window', inject(function(greet, $window) {
greet('World');
expect($window.alert).toHaveBeenCalledWith('Hello World!');
}));
// this is another way of overriding configuration in the
// tests using an inline module and inject methods.
it('should alert using the alert service', function() {
var alertSpy = jasmine.createSpy('alert');
module(function($provide) {
$provide.value('alert', alertSpy);
});
inject(function(greet) {
greet('World');
expect(alertSpy).toHaveBeenCalledWith('Hello World!');
});
});
});
</pre></div>

View file

@ -0,0 +1,222 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>What Is Angular?</h2>
<p>AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template
language and lets you extend HTML's syntax to express your application's components clearly and
succinctly. Out of the box, it eliminates much of the code you currently write through data
binding and dependency injection. And it all happens in JavaScript within the browser making it an
ideal partner with any server technology.</p>
<p>Angular is what HTML would have been had it been designed for applications. HTML is a great
declarative language for static documents. It does not contain much in the way of creating
applications, and as a result building web applications is an exercise in <em>what do I have to do, so
that I trick the browser in to doing what I want.</em></p>
<p>The impedance mismatch between dynamic applications and static documents is often solved as:</p>
<ul>
<li><strong>library</strong> - a collection of functions which are useful when writing web apps. Your code is
in charge and it calls into the library when it sees fit. E.g., <code>jQuery</code>.</li>
<li><strong>frameworks</strong> - a particular implementation of a web application, where your code fills in
the details. The framework is in charge and it calls into your code when it needs something
app specific. E.g., <code>knockout</code>, <code>sproutcore</code>, etc.</li>
</ul>
<p>Angular takes another approach. It attempts to minimize the impedance mismatch between document
centric HTML and what an application needs by creating new HTML constructs. Angular teaches the
browser new syntax through a construct we call directives. Examples include:</p>
<ul>
<li>Data binding as in <code>{{}}</code>.</li>
<li>DOM control structures for repeating/hiding DOM fragments.</li>
<li>Support for forms and form validation.</li>
<li>Attaching code-behind to DOM elements.</li>
<li>Grouping of HTML into reusable components.</li>
</ul>
<h3>End-to-end solution</h3>
<p>Angular tries to be an end-to-end solution, when building a web application. This means it is
not a single piece in an overall puzzle of building a web application, but an end-to-end solution.
This makes Angular opinionated about how a CRUD application should be built. But while it is
opinionated, it also tries to make sure that its opinion is just a starting point, which you can
easily change. Angular comes with the following out-of-the-box:</p>
<ul>
<li>Everything you need to build a CRUD app in a cohesive set: data-binding, basic templating
directives, form validation, routing, deep-linking, reusable components, dependency injection.</li>
<li>Testability story: unit-testing, end-to-end testing, mocks, test harnesses.</li>
<li>Seed application with directory layout and test scripts as a starting point.</li>
</ul>
<h3>Angular Sweet Spot</h3>
<p>Angular simplifies application development by presenting a higher level of abstraction to the
developer. Like any abstraction, it comes at a cost of flexibility. In other words not every app
is a good fit for Angular. Angular was built for the CRUD application in mind. Luckily CRUD
applications represent at least 90% of the web applications. But to understand what Angular is
good at one also has to understand when an app is not a good fit for Angular.</p>
<p>Games, and GUI editors are examples of very intensive and tricky DOM manipulation. These kinds of
apps are different from CRUD apps, and as a result are not a good fit for Angular. In these cases
using something closer to bare metal such as <code>jQuery</code> may be a better fit.</p>
<h2>An Introductory Angular Example</h2>
<p>Below is a typical CRUD application which contains a form. The form values are validated, and
are used to compute the total, which is formatted to a particular locale. These are some common
concepts which the application developer may face:</p>
<ul>
<li>attaching data-model to the UI.</li>
<li>writing, reading and validating user input.</li>
<li>computing new values based on the model.</li>
<li>formatting output in a user specific locale.</li>
</ul>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-73" source-edit-css="" source-edit-js="script.js-72" source-edit-unit="" source-edit-scenario="scenario.js-74"></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-73" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-73">
<div ng-controller="InvoiceCntl">
<b>Invoice:</b>
<br>
<br>
<table>
<tr><td>Quantity</td><td>Cost</td></tr>
<tr>
<td><input type="integer" min="0" ng-model="qty" required ></td>
<td><input type="number" ng-model="cost" required ></td>
</tr>
</table>
<hr>
<b>Total:</b> {{qty * cost | currency}}
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-72"></pre>
<script type="text/ng-template" id="script.js-72">
function InvoiceCntl($scope) {
$scope.qty = 1;
$scope.cost = 19.95;
}
</script>
</div>
<div class="tab-pane" title="End to end test">
<pre class="prettyprint linenums" ng-set-text="scenario.js-74"></pre>
<script type="text/ng-template" id="scenario.js-74">
it('should show of angular binding', function() {
expect(binding('qty * cost')).toEqual('$19.95');
input('qty').enter('2');
input('cost').enter('5.00');
expect(binding('qty * cost')).toEqual('$10.00');
});
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-73" ng-eval-javascript="script.js-72"></div>
<p>Try out the Live Preview above, and then let's walk through the example and describe what's going
on.</p>
<p>In the <code>&lt;html&gt;</code> tag, we specify that it is an Angular
application with the <code>ng-app</code> directive. The <code>ng-app</code> will cause Angular to <a href="guide/bootstrap">auto initialize</a> your application.</p>
<pre><code>&lt;html ng-app&gt;
</code></pre>
<p>We load Angular using the <code>&lt;script&gt;</code> tag:</p>
<pre><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/angularjs/?.?.?/angular.min.js"&gt;&lt;/script&gt;
</code></pre>
<p>From the <code>ng-model</code> attribute of the <code>&lt;input&gt;</code> tags, Angular automatically sets up two-way data
binding, and we also demonstrate some easy input validation:</p>
<pre><code>Quantity: &lt;input type="integer" min="0" ng-model="qty" required &gt;
Cost: &lt;input type="number" ng-model="cost" required &gt;
</code></pre>
<p>These input widgets look normal enough, but consider these points:</p>
<ul>
<li>When this page loaded, Angular bound the names of the input widgets (<code>qty</code> and <code>cost</code>) to
variables of the same name. Think of those variables as the "Model" component of the
Model-View-Controller design pattern.</li>
<li>Note that the HTML widget <a href="api/ng.directive:input"><code>input</code></a>
has special powers. The input invalidates itself by turning red when you enter invalid data or
leave the the input fields blank. These new widget behaviors make it easier to implement field
validation common in CRUD applications.</li>
</ul>
<p>And finally, the mysterious <code>{{ double curly braces }}</code>:</p>
<pre><code> Total: {{qty * cost | currency}}
</code></pre>
<p>This notation, <code>{{ _expression_ }}</code>, is Angular markup for data-binding. The expression itself can
be a combination of both an expression and a <a href="guide/dev_guide.templates.filters">filter</a>: <code>{{
expression | filter }}</code>. Angular provides filters for formatting display data.</p>
<p>In the example above, the expression in double-curly braces directs Angular to "bind the data we
got from the input widgets to the display, multiply them together, and format the resulting number
into output that looks like money."</p>
<p>Notice that we achieved this application behavior not by calling Angular methods, nor by
implementing application specific behavior as a framework. We achieved the behavior because the
browser behaved more in line with what is needed for a dynamic web application rather then what is
needed for a static document. Angular has lowered the impedance mismatch to the point where no
library/framework calls are needed.</p>
<h2>The Zen of Angular</h2>
<p>Angular is built around the belief that declarative code is better than imperative when it comes
to building UIs and wiring software components together, while imperative code is excellent for
expressing business logic.</p>
<ul>
<li>It is a very good idea to decouple DOM manipulation from app logic. This dramatically improves
the testability of the code.</li>
<li>It is a really, <em>really</em> good idea to regard app testing as equal in importance to app
writing. Testing difficulty is dramatically affected by the way the code is structured.</li>
<li>It is an excellent idea to decouple the client side of an app from the server side. This
allows development work to progress in parallel, and allows for reuse of both sides.</li>
<li>It is very helpful indeed if the framework guides developers through the entire journey of
building an app: from designing the UI, through writing the business logic, to testing.</li>
<li>It is always good to make common tasks trivial and difficult tasks possible.</li>
</ul>
<p>Angular frees you from the following pain:</p>
<ul>
<li><strong>Registering callbacks:</strong> Registering callbacks clutters your code, making it hard to see the
forest for the trees. Removing common boilerplate code such as callbacks is a good thing. It
vastly reduces the amount of JavaScript coding <em>you</em> have to do, and it makes it easier to see
what your application does.</li>
<li><strong>Manipulating HTML DOM programmatically:</strong> Manipulating HTML DOM is a cornerstone of AJAX
applications, but it's cumbersome and error-prone. By declaratively describing how the UI
should change as your application state changes, you are freed from low level DOM manipulation
tasks. Most applications written with Angular never have to programmatically manipulate the
DOM, although you can if you want to.</li>
<li><strong>Marshaling data to and from the UI:</strong> CRUD operations make up the majority of AJAX
applications. The flow of marshaling data from the server to an internal object to an HTML
form, allowing users to modify the form, validating the form, displaying validation errors,
returning to an internal model, and then back to the server, creates a lot of boilerplate
code. Angular eliminates almost all of this boilerplate, leaving code that describes the
overall flow of the application rather than all of the implementation details.</li>
<li><strong>Writing tons of initialization code just to get started:</strong> Typically you need to write a lot
of plumbing just to get a basic "Hello World" AJAX app working. With Angular you can bootstrap
your app easily using services, which are auto-injected into your application in a <a href="http://code.google.com/p/google-guice/">Guice</a>-like dependency-injection style. This allows you
to get started developing features quickly. As a bonus, you get full control over the
initialization process in automated tests.</li>
</ul>
<h2>Watch a Presentation About Angular</h2>
<p>Here is a presentation on Angular from May 2012.</p>
<iframe width="560" height="315" src="http://www.youtube.com/embed/bfrn5VNpwsg" frameborder="0" allowfullscreen></iframe></div>

View file

@ -0,0 +1,328 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div><h2>What are Scopes?</h2>
<p><a href="api/ng.$rootScope.Scope"><code>scope</code></a> is an object that refers to the application
model. It is an execution context for <a href="guide/expression">expressions</a>. Scopes are
arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can
watch <a href="guide/expression">expressions</a> and propagate events.</p>
<h3>Scope characteristics</h3>
<ul>
<li><p>Scopes provide APIs (<a href="api/ng.$rootScope.Scope#$watch"><code>$watch</code></a>) to observe
model mutations.</p></li>
<li><p>Scopes provide APIs (<a href="api/ng.$rootScope.Scope#$apply"><code>$apply</code></a>) to
propagate any model changes through the system into the view from outside of the "Angular
realm" (controllers, services, Angular event handlers).</p></li>
<li><p>Scopes can be nested to isolate application components while providing access to shared model
properties. A scope (prototypically) inherits properties from its parent scope.</p></li>
<li><p>Scopes provide context against which <a href="guide/expression">expressions</a> are evaluated. For
example <code>{{username}}</code> expression is meaningless, unless it is evaluated against a specific
scope which defines the <code>username</code> property.</p></li>
</ul>
<h3>Scope as Data-Model</h3>
<p>Scope is the glue between application controller and the view. During the template <a href="guide/compiler">linking</a> phase the <a href="api/ng.$compileProvider#directive"><code>directives</code></a> set up
<a href="api/ng.$rootScope.Scope#$watch"><code><code>$watch</code></code></a> expressions on the scope. The
<code>$watch</code> allows the directives to be notified of property changes, which allows the directive to
render the updated value to the DOM.</p>
<p>Both controllers and directives have reference to the scope, but not to each other. This
arrangement isolates the controller from the directive as well as from DOM. This is an important
point since it makes the controllers view agnostic, which greatly improves the testing story of
the applications.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-76" source-edit-css="" source-edit-js="script.js-75" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-76" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-76">
<div ng-controller="MyController">
Your name:
<input type="text" ng-model="username">
<button ng-click='sayHello()'>greet</button>
<hr>
{{greeting}}
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-75"></pre>
<script type="text/ng-template" id="script.js-75">
function MyController($scope) {
$scope.username = 'World';
$scope.sayHello = function() {
$scope.greeting = 'Hello ' + $scope.username + '!';
};
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-76" ng-eval-javascript="script.js-75"></div>
<p>In the above example notice that the <code>MyController</code> assigns <code>World</code> to the <code>username</code> property of
the scope. The scope then notifies the <code>input</code> of the assignment, which then renders the input
with username pre-filled. This demonstrates how a controller can write data into the scope.</p>
<p>Similarly the controller can assign behavior to scope as seen by the <code>sayHello</code> method, which is
invoked when the user clicks on the 'greet' button. The <code>sayHello</code> method can read the <code>username</code>
property and create a <code>greeting</code> property. This demonstrates that the properties on scope update
automatically when they are bound to HTML input widgets.</p>
<p>Logically the rendering of <code>{{greeting}}</code> involves:</p>
<ul>
<li><p>retrieval of the scope associated with DOM node where <code>{{greeting}}</code> is defined in template.
In this example this is the same scope as the scope which was passed into <code>MyController</code>. (We
will discuss scope hierarchies later.)</p></li>
<li><p>Evaluate the <code>greeting</code> <a href="guide/expression">expression</a> against the scope retrieved above,
and assign the result to the text of the enclosing DOM element.</p></li>
</ul>
<p>You can think of the scope and its properties as the data which is used to render the view. The
scope is the single source-of-truth for all things view related.</p>
<p>From a testability point of view, the separation of the controller and the view is desirable, because it allows us
to test the behavior without being distracted by the rendering details.</p>
<pre class="prettyprint linenums">
it('should say hello', function() {
var scopeMock = {};
var cntl = new MyController(scopeMock);
// Assert that username is pre-filled
expect(scopeMock.username).toEqual('World');
// Assert that we read new username and greet
scopeMock.username = 'angular';
scopeMock.sayHello();
expect(scopeMock.greeting).toEqual('Hello angular!');
});
</pre>
<h3>Scope Hierarchies</h3>
<p>Each Angular application has exactly one <a href="api/ng.$rootScope"><code>root scope</code></a>, but
may have several child scopes.</p>
<p>The application can have multiple scopes, because some <a href="guide/directive">directives</a> create
new child scopes (refer to directive documentation to see which directives create new scopes).
When new scopes are created, they are added as children of their parent scope. This creates a tree
structure which parallels the DOM where they're attached</p>
<p>When Angular evaluates <code>{{username}}</code>, it first looks at the scope associated with the given
element for the <code>username</code> property. If no such property is found, it searches the parent scope
and so on until the root scope is reached. In JavaScript this behavior is known as prototypical
inheritance, and child scopes prototypically inherit from their parents.</p>
<p>This example illustrates scopes in application, and prototypical inheritance of properties.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-79" source-edit-css="style.css-77" source-edit-js="script.js-78" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-79" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-79">
<div ng-controller="EmployeeController">
Manager: {{employee.name}} [ {{department}} ]<br>
Reports:
<ul>
<li ng-repeat="employee in employee.reports">
{{employee.name}} [ {{department}} ]
</li>
</ul>
<hr>
{{greeting}}
</div>
</script>
</div>
<div class="tab-pane" title="style.css">
<pre class="prettyprint linenums" ng-set-text="style.css-77"></pre>
<style type="text/css" id="style.css-77">
/* remove .doc-example-live in jsfiddle */
.doc-example-live .ng-scope {
border: 1px dashed red;
}
</style>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-78"></pre>
<script type="text/ng-template" id="script.js-78">
function EmployeeController($scope) {
$scope.department = 'Engineering';
$scope.employee = {
name: 'Joe the Manager',
reports: [
{name: 'John Smith'},
{name: 'Mary Run'}
]
};
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-79" ng-eval-javascript="script.js-78"></div>
<p>Notice that Angular automatically places <code>ng-scope</code> class on elements where scopes are
attached. The <code>&lt;style&gt;</code> definition in this example highlights in red the new scope locations. The
child scopes are necessary because the repeater evaluates <code>{{employee.name}}</code> expression, but
depending on which scope the expression is evaluated it produces different result. Similarly the
evaluation of <code>{{department}}</code> prototypically inherits from root scope, as it is the only place
where the <code>department</code> property is defined.</p>
<h3>Retrieving Scopes from the DOM.</h3>
<p>Scopes are attached to the DOM as <code>$scope</code> data property, and can be retrieved for debugging
purposes. (It is unlikely that one would need to retrieve scopes in this way inside the
application.) The location where the root scope is attached to the DOM is defined by the location
of <a href="api/ng.directive:ngApp"><code><code>ng-app</code></code></a> directive. Typically
<code>ng-app</code> is placed an the <code>&lt;html&gt;</code> element, but it can be placed on other elements as well, if,
for example, only a portion of the view needs to be controlled by Angular.</p>
<p>To examine the scope in the debugger:</p>
<ol>
<li><p>right click on the element of interest in your browser and select 'inspect element'. You
should see the browser debugger with the element you clicked on highlighted.</p></li>
<li><p>The debugger allows you to access the currently selected element in the console as <code>$0</code>
variable.</p></li>
<li><p>To retrieve the associated scope in console execute: <code>angular.element($0).scope()</code></p></li>
</ol>
<h3>Scope Events Propagation</h3>
<p>Scopes can propagate events in similar fashion to DOM events. The event can be <a href="api/ng.$rootScope.Scope#$broadcast"><code>broadcasted</code></a> to the scope children or <a href="api/ng.$rootScope.Scope#$emit"><code>emitted</code></a> to scope parents.</p>
<h3>Source</h3>
<div source-edit="" source-edit-deps="angular.js script.js" source-edit-html="index.html-81" source-edit-css="" source-edit-js="script.js-80" source-edit-unit="" source-edit-scenario=""></div>
<div class="tabbable"><div class="tab-pane" title="index.html">
<pre class="prettyprint linenums" ng-set-text="index.html-81" ng-html-wrap=" angular.js script.js"></pre>
<script type="text/ng-template" id="index.html-81">
<div ng-controller="EventController">
Root scope <tt>MyEvent</tt> count: {{count}}
<ul>
<li ng-repeat="i in [1]" ng-controller="EventController">
<button ng-click="$emit('MyEvent')">$emit('MyEvent')</button>
<button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button>
<br>
Middle scope <tt>MyEvent</tt> count: {{count}}
<ul>
<li ng-repeat="item in [1, 2]" ng-controller="EventController">
Leaf scope <tt>MyEvent</tt> count: {{count}}
</li>
</ul>
</li>
</ul>
</div>
</script>
</div>
<div class="tab-pane" title="script.js">
<pre class="prettyprint linenums" ng-set-text="script.js-80"></pre>
<script type="text/ng-template" id="script.js-80">
function EventController($scope) {
$scope.count = 0;
$scope.$on('MyEvent', function() {
$scope.count++;
});
}
</script>
</div>
</div><h3>Demo</h3>
<div class="well doc-example-live" ng-embed-app="" ng-set-html="index.html-81" ng-eval-javascript="script.js-80"></div>
<h3>Scope Life Cycle</h3>
<p>The normal flow of a browser receiving an event is that it executes a corresponding JavaScript
callback. Once the callback completes the browser re-renders the DOM and returns to waiting for
more events.</p>
<p>When the browser calls into JavaScript the code executes outside the Angular execution context,
which means that Angular is unaware of model modifications. To properly process model
modifications the execution has to enter the Angular execution context using the <a href="api/ng.$rootScope.Scope#$apply"><code><code>$apply</code></code></a> method. Only model modifications which
execute inside the <code>$apply</code> method will be properly accounted for by Angular. For example if a
directive listens on DOM events, such as <a href="api/ng.directive:ngClick"><code><code>ng-click</code></code></a> it must evaluate the
expression inside the <code>$apply</code> method.</p>
<p>After evaluating the expression, the <code>$apply</code> method performs a <a href="api/ng.$rootScope.Scope#$digest"><code><code>$digest</code></code></a>. In the $digest phase the scope examines all
of the <code>$watch</code> expressions and compares them with the previous value. This dirty checking is done
asynchronously. This means that assignment such as <code>$scope.username="angular"</code> will not
immediately cause a <code>$watch</code> to be notified, instead the <code>$watch</code> notification is delayed until
the <code>$digest</code> phase. This delay is desirable, since it coalesces multiple model updates into one
<code>$watch</code> notification as well as it guarantees that during the <code>$watch</code> notification no other
<code>$watch</code>es are running. If a <code>$watch</code> changes the value of the model, it will force additional
<code>$digest</code> cycle.</p>
<ol>
<li><p><strong>Creation</strong></p>
<p>The <a href="api/ng.$rootScope"><code>root scope</code></a> is created during the application
bootstrap by the <a href="api/AUTO.$injector"><code>$injector</code></a>. During template
linking, some directives create new child scopes.</p></li>
<li><p><strong>Watcher registration</strong></p>
<p>During template linking directives register <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a> on the scope. These watches will be
used to propagate model values to the DOM.</p></li>
<li><p><strong>Model mutation</strong></p>
<p>For mutations to be properly observed, you should make them only within the <a href="api/ng.$rootScope.Scope#$apply"><code>scope.$apply()</code></a>. (Angular APIs do this
implicitly, so no extra <code>$apply</code> call is needed when doing synchronous work in controllers,
or asynchronous work with <a href="api/ng.$http"><code>$http</code></a> or <a href="api/ng.$timeout"><code>$timeout</code></a> services.</p></li>
<li><p><strong>Mutation observation</strong></p>
<p>At the end <code>$apply</code>, Angular performs a <a href="api/ng.$rootScope.Scope#$digest"><code>$digest</code></a> cycle on the root scope, which then propagates throughout all child scopes. During
the <code>$digest</code> cycle, all <code>$watch</code>ed expressions or functions are checked for model mutation
and if a mutation is detected, the <code>$watch</code> listener is called.</p></li>
<li><p><strong>Scope destruction</strong></p>
<p>When child scopes are no longer needed, it is the responsibility of the child scope creator
to destroy them via <a href="api/ng.$rootScope.Scope#$destroy"><code>scope.$destroy()</code></a>
API. This will stop propagation of <code>$digest</code> calls into the child scope and allow for memory
used by the child scope models to be reclaimed by the garbage collector.</p></li>
</ol>
<h4>Scopes and Directives</h4>
<p>During the compilation phase, the <a href="guide/compiler">compiler</a> matches <a href="api/ng.$compileProvider#directive"><code>directives</code></a> against the DOM template. The directives
usually fall into one of two categories:</p>
<ul>
<li><p>Observing <a href="api/ng.$compileProvider#directive"><code>directives</code></a>, such as
double-curly expressions <code>{{expression}}</code>, register listeners using the <a href="api/ng.$rootScope.Scope#$watch"><code>$watch()</code></a> method. This type of directive needs
to be notified whenever the expression changes so that it can update the view.</p></li>
<li><p>Listener directives, such as <a href="api/ng.directive:ngClick"><code>ng-click</code></a>, register a listener with the DOM. When the DOM listener fires, the directive
executes the associated expression and updates the view using the <a href="api/ng.$rootScope.Scope#$apply"><code>$apply()</code></a> method.</p></li>
</ul>
<p>When an external event (such as a user action, timer or XHR) is received, the associated <a href="guide/expression">expression</a> must be applied to the scope through the <a href="api/ng.$rootScope.Scope#$apply"><code>$apply()</code></a> method so that all listeners are updated
correctly.</p>
<h4>Directives that Create Scopes</h4>
<p>In most cases, <a href="api/ng.$compileProvider#directive"><code>directives</code></a> and scopes interact
but do not create new instances of scope. However, some directives, such as <a href="api/ng.directive:ngController"><code>ng-controller</code></a> and <a href="api/ng.directive:ngRepeat"><code>ng-repeat</code></a>, create new child scopes
and attach the child scope to the corresponding DOM element. You can retrieve a scope for any DOM
element by using an <code>angular.element(aDomElement).scope()</code> method call.</p>
<h4>Controllers and Scopes</h4>
<p>Scopes and controllers interact with each other in the following situations:</p>
<ul>
<li><p>Controllers use scopes to expose controller methods to templates (see <a href="api/ng.directive:ngController"><code>ng-controller</code></a>).</p></li>
<li><p>Controllers define methods (behavior) that can mutate the model (properties on the scope).</p></li>
<li><p>Controllers may register <a href="api/ng.$rootScope.Scope#$watch"><code>watches</code></a> on
the model. These watches execute immediately after the controller behavior executes.</p></li>
</ul>
<p>See the <a href="api/ng.directive:ngController"><code>ng-controller</code></a> for more
information.</p>
<h4>Scope <code>$watch</code> Performance Considerations</h4>
<p>Dirty checking the scope for property changes is a common operation in Angular and for this reason
the dirty checking function must be efficient. Care should be taken that the dirty checking
function does not do any DOM access, as DOM access is orders of magnitude slower then property
access on JavaScript object.</p></div>

View file

@ -0,0 +1,4 @@
<h1><code ng:non-bindable=""></code>
<span class="hint"></span>
</h1>
<div></div>