diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/content/guide/concepts.ngdoc | 467 | ||||
| -rw-r--r-- | docs/img/guide/concepts-controller.png | bin | 0 -> 82152 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-directive.png | bin | 0 -> 49545 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-model.png | bin | 0 -> 56006 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-module-injector.png | bin | 0 -> 29568 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-runtime.png | bin | 0 -> 40788 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-scope.png | bin | 0 -> 80187 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-startup.png | bin | 0 -> 34802 bytes | |||
| -rw-r--r-- | docs/img/guide/concepts-view.png | bin | 0 -> 52235 bytes | |||
| -rw-r--r-- | docs/src/example.js | 4 | ||||
| -rw-r--r-- | docs/src/templates/css/docs.css | 9 | 
11 files changed, 478 insertions, 2 deletions
diff --git a/docs/content/guide/concepts.ngdoc b/docs/content/guide/concepts.ngdoc new file mode 100644 index 00000000..77d8c401 --- /dev/null +++ b/docs/content/guide/concepts.ngdoc @@ -0,0 +1,467 @@ +@ngdoc overview +@name Conceptual Overview +@description + +# Overview + +This document gives a quick overview of the main angular components and how they work together. +These are: + +  * {@link concepts#startup startup} - bring up hello world +  * {@link concepts#runtime runtime} - overview of angular runtime +  * {@link concepts#scope scope} - the glue between the view and the controller +  * {@link concepts#controller controller} - application behavior +  * {@link concepts#model model} - your application data +  * {@link concepts#view view} - what the user sees +  * {@link concepts#directives directives} - extend HTML vocabulary +  * {@link concepts#filters filters} - format the data in user locale +  * {@link concepts#injector injector} - assembles your application +  * {@link concepts#module module} - configures the injector +  * {@link concepts#angular_namespace `$`} - angular namespace + +<a name="startup"></a> +# Startup + +This is how we get the ball rolling (refer to the diagram and example below): + +<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png"> + +  1. Browser loads the HTML and parses it into a DOM +  2. Browser loads `angular.js` script +  3. Angular waits for `DOMContentLoaded` event +  4. Angular looks for {@link api/ng.directive:ngApp ng-app} +    {@link guide/directive directive}, which designates application boundary +  5. {@link guide/module Module} specified in {@link +     api/ng.directive:ngApp ng-app} (if any) is used to configure  +     the {@link api/AUTO.$injector $injector} +  6. {@link api/AUTO.$injector $injector} is used to create the {@link +     api/ng.$compile $compile} service as well as {@link +     api/ng.$rootScope $rootScope} +  7. {@link api/ng.$compile $compile} service is used to compile the DOM and link  +     it   with {@link api/ng.$rootScope $rootScope} +  8. {@link api/ng.directive:ngInit ng-init} {@link  +     guide/directive directive} assigns `World` to the `name` property on the {@link guide/scope +     scope} +  9. The `{{name}}` {@link api/ng.$interpolate interpolates} the expression to +     `Hello World!` + +<div class="clear"> +</div> +<example> +  <file name="index.html"> +    <p ng-init=" name='World' ">Hello {{name}}!</p> +  </file> +</example> + + +<a name="runtime"></a> +# Runtime + +<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png"> + +The diagram and the example below describe how Angular interacts with browser's event loop. + +  1. Browsers event-loop waits for an event to arrive. Event is a user interactions, timer event, +     or network event (response from a server). +  2. The events callback gets executed. This enters the JavaScript context. The callback can +      modify the DOM structure. +  3. Once the callback finishes execution, the browser leaves the JavaScript context and +     re-renders the view based on DOM changes. + +Angular modifies the normal JavaScript flow by providing it's 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... Use $apply() to enter Angular execution context from JavaScript. Keep in +mind that in most places (controllers, services) the $apply has already been called for you by the +directive which is handling the event. The need to call $apply is reserved only when +implementing custom event callbacks, or when working with a third-party library callbacks. + +  1. Enter Angular execution context by calling {@link guide/scope scope}`.`{@link +     api/ng.$rootScope.Scope#$apply $apply}`(stimulusFn)`. Where `stimulusFn` is +     the work you wish to do in Angular execution context. +  2. Angular executes the `stimulusFn()`, which typically modifies application state. +  3. Angular enters the {@link api/ng.$rootScope.Scope#$digest $digest} loop. The  +     loop is made up of two smaller loops which process {@link  +     api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue and the {@link +     api/ng.$rootScope.Scope#$watch $watch} list. The {@link +     api/ng.$rootScope.Scope#$digest $digest} loop keeps iterating until the model +     stabilizes, which means that the {@link api/ng.$rootScope.Scope#$evalAsync +     $evalAsync} queue is empty and the {@link api/ng.$rootScope.Scope#$watch +     $watch} list does not detect any changes. +  4. The {@link api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue is used to +     schedule work which needs to occur outside of current stack frame, but before the browser +     view render. This is usually done with `setTimeout(0)`, but the `setTimeout(0)` approach +     suffers from slowness and may cause view flickering since the browser renders the view after +     each event. +  5. The {@link api/ng.$rootScope.Scope#$watch $watch} list is a set of expressions +     which may have changed since last iteration. If a change is detected then the `$watch` +     function is called which typically updates the DOM with the new value. +  6. Once Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes  +     the execution leaves the Angular and JavaScript context. This is followed by the browser +     re-rendering the DOM to reflect any changes. + + +Here is the explanation of how the `Hello wold` example achieves the data-binding effect when the +user enters text into the text field. + +  1. During the compilation phase: +     1. the {@link api/ng.directive:ngModel ng-model} and {@link +        api/ng.directive:input input} {@link guide/directive +        directive} set up a `keydown` listener on the `<input>` control. +     2. the {@link api/ng.$interpolate {{name}} } interpolation +        sets up a {@link api/ng.$rootScope.Scope#$watch $watch} to be notified of +        `name` changes. +  2. During the runtime phase: +     1. Pressing an '`X`' key causes the browser to emit a `keydown` event on the input control. +     2. The {@link api/ng.directive:input input} directive +        captures the change to the input's value and calls {@link +        api/ng.$rootScope.Scope#$apply $apply}`("name = 'X';")` to update the +        application model inside the Angular execution context. +     3. Angular applies the `name = 'X';` to the model. +     4. The {@link api/ng.$rootScope.Scope#$digest $digest} loop begins +     5. The {@link api/ng.$rootScope.Scope#$watch $watch} list detects a change +        on the `name` property and notifies the {@link api/ng.$interpolate +        {{name}} } interpolation, which in turn updates the DOM. +     6. Angular exits the execution context, which in turn exits the `keydown` event and with it  +        the JavaScript execution context. +     7. The browser re-renders the view with update text. + +<div class="clear"> +</div> +<example> +  <file name="index.html"> +    <input ng-model="name"> +    <p>Hello {{name}}!</p> +  </file> +</example> + +<a name="scope"></a> +#Scope + +The {@link guide/scope scope} is responsible for detecting changes to the model section and +provides the execution context for expressions. The scopes are nested in a hierarchical structure +which closely follow the DOM structure. (See individual directive documentation to see which +directives cause a creation of new scopes.) + +The following example demonstrates how `name` {@link guide/expression expression} will evaluate +into different value depending on which scope it is evaluated in. The example is followed by +a diagram depicting the scope boundaries. + +<div class="clear"> +</div> +<div class="show-scope"> +<example> +  <file name="index.html"> +    <div ng-controller="GreetCtrl"> +      Hello {{name}}! +    </div> +    <div ng-controller="ListCtrl"> +      <ol> +        <li ng-repeat="name in names">{{name}}</li> +      </ol> +    </div> +  </file> +  <file name="script.js"> +    function GreetCtrl($scope) { +      $scope.name = 'World'; +    } +     +    function ListCtrl($scope) { +      $scope.names = ['Igor', 'Misko', 'Vojta']; +    } +  </file> +  <file name="style.css"> +    .show-scope .doc-example-live.ng-scope, +    .show-scope .doc-example-live .ng-scope  { +      border: 1px solid red; +      margin: 3px; +    } +  </file> +</example> +</div> + +<img class="center" src="img/guide/concepts-scope.png"> + + +<a name="controller"></a> +# Controller + +<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png"> + +Controller is the code behind the view. Its job is to construct the model and publish it to the +view along with callback methods. The view is a projection of the scope onto the template (the +HTML). The scope is the glue which marshals the model to the view and forwards the events to the +controller. + +The separation of the controller and the view is important because: + +  * The controller is written in JavaScript. JavaScript is imperative. Imperative is a good fit +    for specifying application behavior. The controller should not contain any rendering  +    information (DOM references or HTML fragments). +  * The view template is written in HTML. HTML is declarative. Declarative is a good fit for +    specifying UI. The View should not contain any behavior. +  * Since the controller is unaware of the view, there could be many views for the same +    controller. This is important for re-skinning, device specific views (i.e. mobile vs desktop), +    and testability. + +<div class="clear"> +</div> +<example> +  <file name="index.html"> +    <div ng-controller="MyCtrl"> +      Hello {{name}}! +      <button ng-click="action()"> +        OK +      </button> +    </div> +  </file> +  <file name="script.js"> +    function MyCtrl($scope) { +      $scope.action = function() { +        $scope.name = 'OK'; +      } +       +      $scope.name = 'World'; +    } +  </file> +</example> + + +<a name="model"></a> +# Model + +<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png"> + +The model is the data which is used merged with the template to produce the view. To be able to +render the model into the view, the model has to be referenceable 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. + + +<div class="clear"> +</div> + + +<a name="view"></a> +# View + +<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-view.png"> + +The view is what the 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, to most other templating systems.  + +  * **Others** - Most templating systems begin as an HTML string with special templating markup. +    Often the template markup breaks the HTML syntax which means that the template can not be +    edited by an HTML editor. The template string is then parsed by the template engine, and +    merged with the data. The result of the merge is an HTML string. The HTML string is then +    written to the browser using the `.innerHTML`, which causes the browser to render the HTML. +    When the model changes the whole process needs to be repeated. The granularity of the template +    is the granularity of the DOM updates. The key here is that the templating system manipulates +    strings. +  * **Angular** - Angular is different, since its templating system works on DOM objects not on  +    strings. The template is still written in HTML string, but it is HTML (not HTML with +    template sprinkled in.) The browser parses the HTML into DOM, and the DOM becomes the input to +    the template engine know as the {@link api/ng.$compile compiler}. The compiler +    looks for {@link guide/directive directives} which in turn set up {@link +    api/ng.$rootScope.Scope#$watch watches} on the model. The result is a +    continuously updating view which does not need template model re-merging. Your model becomes  +    the single source-of-truth for your view. + +<div class="clear"> +</div> + +<example> +  <file name="index.html"> +    <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] "> +      <input ng-model="list" ng-list> <br> +      <input ng-model="list" ng-list> <br> +      <pre>list={{list}}</pre> <br> +      <ol> +        <li ng-repeat="item in list"> +          {{item}} +        </li> +      </ol> +    </div> +  </file> +</example> + + +<a name="directives"></a> +# Directives + +A directive is a behavior or DOM transformation which is triggered by a presence of an 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 `contenteditable` +in HTML. + +<example module="directive"> +  <file name="script.js"> +    angular.module('directive', []).directive('contenteditable', function() { +      return { +        require: 'ngModel', +        link: function(scope, elm, attrs, ctrl) { +          // view -> model +          elm.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()); +        } +      }; +    }); +  </file> +  <file name="index.html"> +    <div contentEditable="true" ng-model="content">Edit Me</div> +    <pre>model = {{content}}</pre> +  </file> +  <file name="style.css"> +    div[contentEditable] { +      cursor: pointer; +      background-color: #D0D0D0; +      margin-bottom: 1em; +      padding: 1em; +    } +  </file> +</example> + +<a name="filters"></a> +# Filters + +{@link api/ng.$filter Filters} perform data transformation roles. Typically +they are used in conjunction with the locale to format the data in locale specific output. +They are follow the spirit of UNIX filters and follow similar syntax `|` (pipe). + +<example> +  <file name="index.html"> +    <div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] "> +      Number formatting: {{ 1234567890 | number }} <br> +      array filtering <input ng-model="predicate">  +      {{ list | filter:predicate | json }} +    </div> +  </file> +</example> + + +<a name="module"></a> +<a name="injector"></a> +# Modules and the Injector + +<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png"> + +An {@link api/AUTO.$injector injector} is a service locator. There is a single +{@link api/AUTO.$injector injector} per Angular {@link +api/ng.directive:ngApp application}. The {@link +api/AUTO.$injector injector} provides a way to look up an object instance by its +name. The injector keeps on internal cache of all objects so that repeated calls to get the same +object name result in the same instance. If the object does not exist, then the {@link +api/AUTO.$injector injector} asks the instance factory to create a new instance. + +A {@link api/angular.Module module} is a way to configure the injector's instance factory, known +as a {@link api/AUTO.$provide provider}. + +<div class='clear'></div> +<pre> +  // Create a module +  var myModule = angular.module('myModule', []) +   +  // Configure the injector +  myModule.factory('serviceA', function() { +    return { +      // instead of {}, put your object creation here +    }; +  }); +   +  // create an injector and configure it from 'myModule' +  var $injector = angular.injector('myModule'); +   +  // retrieve an object from the injector by name +  var serviceA = $injector.get('serviceA'); +   +  // always true because of instance cache +  $injector.get('serviceA') === $injector.get('serviceA'); +</pre> + + +But the real magic of the {@link api/AUTO.$injector injector} is that it can be +used to {@link api/AUTO.$injector#invoke call} methods and {@link +api/AUTO.$injector#instantiate instantiate} types. This subtle feature is what +allows the methods and types to ask for their dependencies rather then to look for them. + +<pre> +  // You write functions such as this one. +  function doSomething(serviceA, serviceB) { +    // do something here. +  } + +  // Angular provides the injector for your application +  var $injector = ...; +   +  /////////////////////////////////////////////// +  // the old-school way of getting dependencies. +  var serviceA = $injector.get('serviceA'); +  var serviceB = $injector.get('serviceB'); +   +  // now call the function +  doSomething(serviceA, serviceB); + +  /////////////////////////////////////////////// +  // the cool way of getting dependencies. +  // the $injector will supply the arguments to the function automatically +  $injector.invoke(doSomething); // This is how the framework calls your functions +</pre> + +Notice that the only thing you needed to write was the function, and list the dependencies in the +function arguments. When angular calls the function, it will use the {@link +api/AUTO.$injector#invoke call} which will automatically fill the function +arguments. + +Examine the `ClockCtrl` bellow, and notice how it list the dependencies in constructor. When the +{@link api/ng.directive:ngController ng-controller} instantiates +the controller it automatically provides the dependencies. There is no need to create +dependencies, look for dependencies, or even get a reference to the injector. + +<example module="timeExampleModule"> +  <file name="index.html"> +    <div ng-controller="ClockCtrl"> +      Current time is: {{ time.now }} +    </div> +  </file> +  <file name="script.js"> +    angular.module('timeExampleModule', []). +      // Declare new object call 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; +    } +  </file> +</example> + + +<a name="angular_namespace"></a> +# Angular Namespace + +To prevent accidental name collision, Angular prefixes names of objects which could potentially +collide with `$`. Please do not use the `$` prefix in your code as it may accidentally collide +with Angular code. diff --git a/docs/img/guide/concepts-controller.png b/docs/img/guide/concepts-controller.png Binary files differnew file mode 100644 index 00000000..91f3e76f --- /dev/null +++ b/docs/img/guide/concepts-controller.png diff --git a/docs/img/guide/concepts-directive.png b/docs/img/guide/concepts-directive.png Binary files differnew file mode 100644 index 00000000..b77d5f8e --- /dev/null +++ b/docs/img/guide/concepts-directive.png diff --git a/docs/img/guide/concepts-model.png b/docs/img/guide/concepts-model.png Binary files differnew file mode 100644 index 00000000..ac6db023 --- /dev/null +++ b/docs/img/guide/concepts-model.png diff --git a/docs/img/guide/concepts-module-injector.png b/docs/img/guide/concepts-module-injector.png Binary files differnew file mode 100644 index 00000000..31fcf84c --- /dev/null +++ b/docs/img/guide/concepts-module-injector.png diff --git a/docs/img/guide/concepts-runtime.png b/docs/img/guide/concepts-runtime.png Binary files differnew file mode 100644 index 00000000..eededc2a --- /dev/null +++ b/docs/img/guide/concepts-runtime.png diff --git a/docs/img/guide/concepts-scope.png b/docs/img/guide/concepts-scope.png Binary files differnew file mode 100644 index 00000000..83ad8f8f --- /dev/null +++ b/docs/img/guide/concepts-scope.png diff --git a/docs/img/guide/concepts-startup.png b/docs/img/guide/concepts-startup.png Binary files differnew file mode 100644 index 00000000..b896a2b5 --- /dev/null +++ b/docs/img/guide/concepts-startup.png diff --git a/docs/img/guide/concepts-view.png b/docs/img/guide/concepts-view.png Binary files differnew file mode 100644 index 00000000..0222544b --- /dev/null +++ b/docs/img/guide/concepts-view.png diff --git a/docs/src/example.js b/docs/src/example.js index c85e1d0e..7477b0a5 100644 --- a/docs/src/example.js +++ b/docs/src/example.js @@ -58,10 +58,10 @@ exports.Example.prototype.addSource = function(name, content) {  };  exports.Example.prototype.toHtml = function() { -  return '<h1>Source</h1>\n' + +  return '<h2>Source</h2>\n' +            this.toHtmlEdit() +            this.toHtmlTabs() + -          '<h1>Demo</h1>\n' + +          '<h2>Demo</h2>\n' +            this.toHtmlEmbed();  }; diff --git a/docs/src/templates/css/docs.css b/docs/src/templates/css/docs.css index a262eb9c..53478e33 100644 --- a/docs/src/templates/css/docs.css +++ b/docs/src/templates/css/docs.css @@ -145,6 +145,11 @@ ul.events > li > h3 {    font-family: monospace;  } +.center { +  display: block; +  margin: 2em auto; +} +  .diagram {    display: block;    margin: 2em auto; @@ -175,3 +180,7 @@ ul.events > li > h3 {    color: white;    text-decoration: none;  } + +.clear { +  clear: both; +}  | 
