diff options
| author | Misko Hevery | 2011-12-14 02:55:31 +0100 | 
|---|---|---|
| committer | Misko Hevery | 2012-01-25 11:53:59 -0800 | 
| commit | 4804c83b7db5770d5d02eea9eea4cc012b4aa524 (patch) | |
| tree | be5ae1743179704cc1638f186cddba8d6e3fa37d /docs | |
| parent | e2b1d9e994e50bcd01d237302a3357bc7ebb6fa5 (diff) | |
| download | angular.js-4804c83b7db5770d5d02eea9eea4cc012b4aa524.tar.bz2 | |
docs(compiler): update the compiler docs
Diffstat (limited to 'docs')
33 files changed, 657 insertions, 644 deletions
| diff --git a/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc b/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc new file mode 100644 index 00000000..5a258179 --- /dev/null +++ b/docs/content/api/angular.module.ng.$compileProvider.directive.ngdoc @@ -0,0 +1,505 @@ +@ngdoc overview +@name angular.module.ng.$compileProvider.directive +@description + +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. + +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). + +# Invoking directives from HTML + +Directives have camel cased names such as 'ngBind'. The directive can be invoked by translating +the camel case name into snake case with these special characters `:`, `-`, or `_`. Optionally the +directive can be prefixed with `x-`, or `data-` to make it HTML validator compliant. Here is a +list of some of the possible directive names: `ng:bind`, `ng-bind`, `ng_bind`, `x-ng-bind` and +`data-ng-bind`. + +The directives can be placed in element names, attributes, class names, as well as comments. Here +are some equivalent examples of invoking `ngBind`. + +<pre> +  <span ng-bind="exp"></span> +  <span class="ng-bind: exp;"></span> +  <ng-bind></ng-bind> +  <!-- directive: ng-bind exp --!> +</pre> + +Directives can be invoked in many different ways, but are equivalent in the end result as shown in +the following example. + +<doc:example> +  <doc:source > +   <script> +     function Ctrl1($scope) { +       $scope.name = 'angular'; +     } +   </script> +   <div ng-controller="Ctrl1"> +     Hello <input ng-model='name'> <hr/> +     <span ng:bind="name"> <span ng:bind="name"></span> <br/> +     <span ng_bind="name"> <span ng_bind="name"></span> <br/> +     <span ng-bind="name"> <span ng-bind="name"></span> <br/> +     <span data-ng-bind="name"> <span data-ng-bind="name"></span> <br/> +     <span x-ng-bind="name"> <span x-ng-bind="name"></span> <br/> +     <span class="ng-bind: name;"> <span class="ng-bind: name;"></span> <br/> +   </div> +  </doc:source> +  <doc:scenario> +    it('should load template1.html', function() { +      expect(element('div[ng-controller="Ctrl1"] span[ng-bind]').text()).toBe('angular'); +    }); +  </doc:scenario> +</doc:example> + +# String interpolation + +During the compilation process the {@link angular.module.ng.$compile compiler} matches text and +attributes using the {@link angular.module.ng.$interpolate $interpolate} service to see if they +contain embedded expressions. These expressions are registered as {@link +angular.module.ng.$rootScope.Scope#.watch watches} and will update as part of normal {@link +angular.module.ng.$rootScope.Scope#.digest digest} cycle. An example of interpolation is shown +here: + +<pre> +<img src="img/{{username}}.jpg">Hello {{username}}!</img> +</pre> + +# Compilation process, and directive matching + +Compilation of HTML happens in three phases: + +  1. 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 then on DOM elements. + +  2. The compilation of the DOM is performed by the call to {@link angular.module.ng.$compile +  $compile()} 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 `compile()` +  functions are executed. The directive compile function has a chance to modify the DOM structure +  and is responsible for producing a `link()` function explained next. The {@link +  angular.module.ng.$compile $compile()} method returns a combined linking function, which is a +  collection of all of the linking functions returned from the individual directive compile +  functions. + +  3. Link the template with scope by calling the liking 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 {@link +  angular.module.ng.$rootScope.Scope#.watch watches} with the {@link +  angular.module.ng.$rootScope.Scope scope}. The result of this is a live binding between the +  scope and the DOM. A change in the scope is reflected in the DOM. + +<pre> +  var $compile = ...; // injected into your code +  var scope = ...; + +  var html = '<div ng-bind='exp'></div>'; + +  // 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> + +## Reasons behind the compile/link separation + +At this point you may wonder why is the compile process broken down to a compile and link phase. +To understand this, lets look at a real world example with repeater: + +<pre> +  Hello {{user}}, you have these actions: +  <ul> +    <li ng:repeat="action in user.actions"> +      {{action.description}} +    </li> +  </ul> +</pre> + +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. + +When the above example is compiled, the compiler visits every node and looks for directives. The +`{{user}}` is an example of {@link angular.module.ng.$interpolate interpolation} directive. {@link +angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} is another directive. But {@link +angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} has a dilemma. It needs to be +able to quickly stamp out new `li`s for every `action` in `user.actions`. This means that it needs +to save a clean copy of the `li` element for cloning purposes and as new `action`s are inserted, +the template `li` element needs to be cloned and inserted into `ul`. But cloning the `li` element +is not enough. It also needs to compile the `li` so that its directives such as +`{{action.descriptions}}` evaluate against the right {@link angular.module.ng.$rootScope.Scope +scope}. A naive method would be to simply insert a copy of the `li` elemnt and then compile it. +But compiling on every `li` 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 problem. + +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 {@link angular.module.ng.$rootScope.Scope scope} and the specific +instance of an `li` is performed. + +{@link angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} works by preventing the +compilation process form descending into `li` element. Instead the {@link +angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} directive compiles `li` +seperatly. The result of of the `li` element compilation is a linking function which contains all +of the directives contained in the `li` element ready to be attached to a specific clone of `li` +element. At runtime the {@link angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} +watches the expression and as items are added to the array it clones the `li` element, creates a +new {@link angular.module.ng.$rootScope.Scope scope} for the cloned `li` element and calls the +link function on the cloned `li`. + +Summary: + +  * *compile function* - The compile function is relatively rare in directives, since most +    directives are concerned with working with a specific DOM element instance rather then +    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. + +  * *link function* - It is rare for the directive not to have a link function. 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. + + +# Writing directives (short version) + +In this example we will build a directive which displays the current time. + +<doc:example module="time"> +  <doc:source> +   <script> +     function Ctrl2($scope) { +       $scope.format = 'M/d/yy h:mm:ss a'; +     } + +     angular.module('time', [], function($compileProvider) { +       // Register the 'myCurrentTime' directive factory method. +       // We inject $defer and dateFilter service since the factory method is DI. +       $compileProvider.directive('myCurrentTime', function($defer, dateFilter) { +         // return the directive link function. (compile function not needed) +         return function(scope, element, attrs) { +           var format,  // date format +               deferId; // deferId, 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 deferId for canceling +             deferId = $defer(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() { +             $defer.cancel(deferId); +           }); + +           updateLater(); // kick of the UI update process. +         } +       }); +     }); + +   </script> +   <div ng-controller="Ctrl2"> +     Date format: <input ng-model='format'> <hr/> +     Current time is: <span my-current-time="format"></span +   </div> +  </doc:source> +  <doc:scenario> +  </doc:scenario> +</doc:example> + + +# Writing directives (long version) + +The full skeleton of the directive is shown here: + +<pre> +  var $compileProvider = ...; + +  $compileProvider.directive('directiveName', function factory(injectables) { +    var directiveDefinitionObject = { +      priority: 0, +      template: '<div></div>', +      templateUrl: 'directive.html', +      restrict: 'EACM', +      scope: false, +      compile: function compile(tElement, tAttrs) { +        return { +          pre: function preLink(scope, iElement, iAttrs) { ... }, +          post: function postLink(scope, iElement, iAttrs) { ... } +        } +      }, +      link: function postLink(scope, iElement, iAttrs) { ... } +    }; +    return directiveDefinitionObject; +  }); +</pre> + +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 isomers of this skeleton. + +It is rare that you need `preLink` method since most directives use the `postLink` method. +Therefore the above can be simplified as: + +<pre> +  var $compileProvider = ...; + +  $compileProvider.directive('directiveName', function factory(injectables) { +    var directiveDefinitionObject = { +      compile: function compile(tElement, tAttrs) { +        return function postLink(scope, iElement, iAttrs) { ... } +      } +    }; +    return directiveDefinitionObject; +  }); +</pre> + +Most directives concern themselves only with instances not with template transformations allowing +further simplification: + +<pre> +  var $compileProvider = ...; + +  $compileProvider.directive('directiveName', function factory(injectables) { +    return function postLink(scope, iElement, iAttrs) { ... } +  }); +</pre> + + +## Factory method + +The factory method is responsible for creating the directive. It is invoked only once, when the +{@link angular.module.ng.$compile compiler} matches the directive for the first time. You can +perform any initialization work here. The method is invoked using the {@link +http://localhost:8000/build/docs/api/angular.module.AUTO.$injector#invoke $injector.invoke} which +makes it injectable following all of the rules of injection annotation. + +## Directive Definition Object + +The directive definition object provides instructions to the {@link angular.module.ng.$compile +compiler}. The attributes are: + +  * `priority` - 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 `priority` is used +    to sort the directives before their `compile` functions get called. Higher `priority` goes +    first. The order of directives within the same priority is undefined. + +  * `terminal` - If set to true then the current `priority` will be the last set of directives +    which will execute (this means that any directives at the current priority will still execute +    as the order of execution on same `priority` is undefined). + +  * `scope` - If set to true, then a new scope will be created for this directive. It is an error +    to have two directives on the same element both requesting new scope. The new scope rule does +    not apply for the root of the template since the root of the template always gets a new scope. + +  * `restrict` - String of subset of `EACM` which restricts the directive to a specific directive +    declaration style. + +    * `E` - Element name: `<my-directive></my-directive>` +    * `A` - Attribute: `<div my-directive="exp"></div>` +    * `C` - Class: `<div class="my-directive: exp;"></div>` +    * `M` - Comment: `<!-- directive: my-directive exp -->` + +  * `template` - replace the current element with the contents of the HTML. The HTML may have +    `<<content>>` string embedded in itself, in which case the current element content +    will be transferred there. 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. + +  * `templateURL` - Same as `template` 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. + +  * `compile`: This is the compile function described in the section below. + +  * `link`: This is the link function described in the section below. This property is used only +    if the `compile` property is not defined. + +## Compile function + +<pre> +  function compile(tElement, tAttrs) { ... } +</pre> + +Compile function deals with transforming the template DOM. Since most directives do not do +template transformation, it is not used often. Examples which require compile functions are +directives which transform template DOM such as {@link +angular.module.ng.$compileProvider.directive.ng:repeat ng:repeat} or load the contents +asynchronously such as {@link angular.module.ng.$compileProvider.directive.ng:view ng:view}. The +compile functions takes the following arguments. + +  * `tElement` - template element - The element where the directive has been declared. It is +    safe to do template transformation on the element and child elements only. + +  * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared +    between all directive compile functions. See {@link +    angular.module.ng.$compileProvider.directive.Attributes Attributes} + +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 to do anything other the DOM transformation. +Specifically listener registration as not allowed inside the compile function. + +## Link function + +<pre> +  function link(scope, iElement, iAttrs) { ... } +</pre> + +Compile 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. + +  * `scope` - {@link angular.module.ng.$rootScope.Scope Scope} - The scope to be used be the +    directive for registering {@link angular.module.ng.$rootScope.Scope#.watch watches}. + +  * `iElement` - instance element - The element where the directive is to be used. It is safe to +    manipulate the children of the element only in `postLink` function since the children have +    already been linked. + +  * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared +    between all directive linking functions. See {@link +    angular.module.ng.$compileProvider.directive.Attributes Attributes} + + +### Pre link function + +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. + +### Post link function + +Executed after the child elements are linked. Safe to do DOM transformation in here. + +## Attributes + +Attributes object is a way of accessing element attributes which: + +  * *normalize attribute names:* Since a directive such as 'ngBind' can be expressed in many ways +    sucha s as 'ng:bind', or 'x-ng-bind', the attributes object allows for a normalize accessed to +    the attributes. + +  * *directive inter-communication:* All directives share the same instance of the attributes +    object which allows the directives to use the attributes object as inter directive +    communication. + +  * *supports interpolation:* Interpolation attributes are assigned to the attribute object +    allowing other directives to read the interpolated value. + + +# Creating Widgets + +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. + +Following is an example of building a reusable widget. + + +<doc:example module="zippyModule"> +  <doc:source> +   <script> +     function Ctrl3($scope) { +       $scope.title = 'Lorem Ipsum'; +       $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; +     } + +     angular.module('zippyModule', [], function($compileProvider) { +       $compileProvider.directive('zippy', function(){ +         return { +           // This HTML will replace the zippy directive. +           replace: true, +           template: '<div>' + +                       '<div class="title"></div>' + +                       '<div class="body"><<content>></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; + +             // Watch the zippy-title attribute, copy changes to title element +             scope.$watch( +               function(){ return attrs.zippyTitle; }, +               function(value) { return title.text(value); } +             ); + +             // 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> +   <style> +     .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 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> +  </doc:source> +  <doc:scenario> +    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/); +    }); +  </doc:scenario> +</doc:example> + + diff --git a/docs/content/api/index.ngdoc b/docs/content/api/index.ngdoc index ccacef80..9f1bb398 100644 --- a/docs/content/api/index.ngdoc +++ b/docs/content/api/index.ngdoc @@ -4,9 +4,7 @@  ## Angular Compiler API -* {@link angular.widget Widgets} - Angular custom DOM element -* {@link angular.directive Directives} - Angular DOM element attributes -* {@link angular.markup Markup} and {@link angular.attrMarkup Attribute Markup} +* {@link angular.module.ng.$compileProvider.directive Directives} - Angular DOM element attributes  * {@link angular.module.ng.$filter Filters} - Angular output filters  * {@link angular.module.ng.$compile $compile} - Template compiler diff --git a/docs/content/cookbook/deeplinking.ngdoc b/docs/content/cookbook/deeplinking.ngdoc index a4dc3a9b..1d6d196b 100644 --- a/docs/content/cookbook/deeplinking.ngdoc +++ b/docs/content/cookbook/deeplinking.ngdoc @@ -102,11 +102,10 @@ The two partials are defined in the following URLs:  * Routes are defined in the `AppCntl` class. The initialization of the controller causes the    initialization of the {@link api/angular.module.ng.$route $route} service with the proper URL -routes. +  routes.  * The  {@link api/angular.module.ng.$route $route} service then watches the URL and instantiates the    appropriate controller when the URL changes. -* The  {@link api/angular.widget.ng:view ng:view} widget loads the view when the URL changes. It -also -  sets the view scope to the newly instantiated controller. +* The  {@link api/angular.module.ng.$compileProvider.directive.ng:view ng:view} widget loads the +  view when the URL changes. It also sets the view scope to the newly instantiated controller.  * Changing the URL is sufficient to change the controller and view. It makes no difference whether    the URL is changed programatically or by the user. diff --git a/docs/content/cookbook/form.ngdoc b/docs/content/cookbook/form.ngdoc index 9371da7a..b811a1fc 100644 --- a/docs/content/cookbook/form.ngdoc +++ b/docs/content/cookbook/form.ngdoc @@ -102,12 +102,12 @@ allow a user to enter data.  # Things to notice -* The user data model is initialized {@link api/angular.directive.ng:controller controller} and is -available in -  the {@link api/angular.module.ng.$rootScope.Scope scope} with the initial data. +* The user data model is initialized {@link api/angular.module.ng.$compileProvider.directive.ng:controller controller} and is +  available in the {@link api/angular.module.ng.$rootScope.Scope scope} with the initial data.  * For debugging purposes we have included a debug view of the model to better understand what    is going on. -* The {@link api/angular.widget.input input widgets} simply refer to the model and are data-bound. +* The {@link api/angular.module.ng.$compileProvider.directive.input input directives} simply refer +  to the model and are data-bound.  * The inputs {@link guide/dev_guide.forms validate}. (Try leaving them blank or entering non digits    in the zip field)  * In your application you can simply read from or write to the model and the form will be updated. diff --git a/docs/content/cookbook/helloworld.ngdoc b/docs/content/cookbook/helloworld.ngdoc index b6b5bcf7..0d9f882a 100644 --- a/docs/content/cookbook/helloworld.ngdoc +++ b/docs/content/cookbook/helloworld.ngdoc @@ -29,7 +29,8 @@  Take a look through the source and note:  * The script tag that {@link guide/dev_guide.bootstrap bootstraps} the angular environment. -* The text {@link api/angular.widget.input input widget} which is bound to the greeting name text. +* The text {@link api/angular.module.ng.$compileProvider.directive.input input widget} which is +  bound to the greeting name text.  * No need for listener registration and event firing on change events.  * The implicit presence of the `name` variable which is in the root {@link api/angular.module.ng.$rootScope.Scope scope}.  * The double curly brace `{{markup}}`, which binds the name variable to the greeting text. diff --git a/docs/content/guide/dev_guide.bootstrap.ngdoc b/docs/content/guide/dev_guide.bootstrap.ngdoc index 5b688e3a..83b26aea 100644 --- a/docs/content/guide/dev_guide.bootstrap.ngdoc +++ b/docs/content/guide/dev_guide.bootstrap.ngdoc @@ -31,18 +31,19 @@ and manage the whole page. You do this as follows:  You need to declare the angular namespace declaration in the following cases: -* For all browsers if you are using XHTML. -* For Internet Explorer older than version 9 (because older versions of IE do not render widgets +* For all types of browser if you are using XHTML. +* For Internet Explorer older than version 9 (because older versions of IE do not render namespace  properly for either HTML or XHTML).  ## Creating Your Own Namespaces -When you are ready to define your own {@link dev_guide.compiler.widgets widgets}, you must create -your own namespace in addition to specifying the angular namespace. You use your own namespace to -form the fully qualified name for widgets that you create. +When you are ready to define your own {@link api/angular.module.ng.$compileProvider.directive +directive}, you may chose to create your own namespace in addition to specifying the angular +namespace. You use your own namespace to form the fully qualified name for directives that you +create. -For example, you could map the alias `my` to your domain, and create a widget called `my:widget`. +For example, you could map the alias `my` to your domain, and create a directive called `my:directive`.  To create your own namespace, simply add another `xmlns` tag to your page, create an alias, and set  it to your unique domain: diff --git a/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc b/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc deleted file mode 100644 index 2d6723cf..00000000 --- a/docs/content/guide/dev_guide.compiler.directives.creating_directives.ngdoc +++ /dev/null @@ -1,38 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Directives: Creating Custom Angular Directives -@description - -The following code snippet shows how to define a custom directive. You define a new directive by -extending the {@link dev_guide.compiler Angular HTML compiler}. The code snippet below is a -simplified definition of the built-in {@link api/angular.directive.ng:bind ng:bind} directive: - -<pre> -angular.directive('ng:bind', function(expression, compiledElement) { -    var compiler = this; -    return function(linkElement) { -        var currentScope = this; -        currentScope.$watch(expression, function(value) { -            linkElement.text(value); -        }); -    }; -}); -</pre> - -# Additional Compiler Methods for Custom Directives - -The angular compiler exposes methods that you may need to use when writing your own widgets and -directives.  For example, the `descend()` method lets you control whether the compiler ignores or -processes child elements of the element it is compiling.  For information on this and other -compiler methods, see the {@link api/angular.module.ng.$compile Compiler API doc}. - - -## Related Docs - -* {@link dev_guide.compiler.directives Understanding Angular Directives} -* {@link dev_guide.compiler.directives_widgets Comparing Directives and Widgets} -* {@link dev_guide.compiler Angular HTML Compiler} - - -## Related API - -* {@link api/angular.directive Angular Directive API}. diff --git a/docs/content/guide/dev_guide.compiler.directives.ngdoc b/docs/content/guide/dev_guide.compiler.directives.ngdoc deleted file mode 100644 index 651a8815..00000000 --- a/docs/content/guide/dev_guide.compiler.directives.ngdoc +++ /dev/null @@ -1,47 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Understanding Angular Directives -@description - -An angular directive is a custom HTML attribute that angular knows how to process.  You add them to -a template element like any other attribute.  Angular directives all have a `ng:` prefix.  In the -following example, the angular directive (`ng:controller`) is  a div tag: - -        <div ng:controller> - -You use angular directives to modify DOM element properties. The element you modify can be an -existing HTML element type or a custom DOM element type that you created. You can use any number of -directives per element. - -You add angular directives to a standard HTML tag as in the following example, in which we have -added the {@link api/angular.directive.ng:click ng:click} directive to a button tag: - -        <button ng:click="foo()">Click This</button> - -The `ng:click` directive lets you specify click event handlers directly in the template. Unlike the -evil `onclick` attribute, the expression associated with the `ng:click` directive is always executed -in the context of the current angular scope. - -In the next example, we add the {@link api/angular.directive.ng:bind ng:bind} directive to a -`<span>` tag: - -        <span ng:bind="1+2"></span> - -The `ng:bind` directive tells angular to set up {@link dev_guide.templates.databinding data -binding} between the data model and the view for the specified expression.  When the angular {@link -dev_guide.compiler compiler} encounters an `ng:bind` directive in a template, it passes the -attribute value to the `ng:bind` function, which in turn sets up the data binding. On any change to -the model that would change the result of the expression, the view is updated and the text of the -span element will reflect the new value. In the example above, the model is represented by two -constants, so nothing will ever change - Sorry! - - -## Related Topics - -* {@link dev_guide.compiler Angular HTML Compiler} -* {@link dev_guide.compiler.directives.creating_directives Creating Angular Directives} -* {@link dev_guide.compiler.directives_widgets Comparing Directives and Widgets} - -## Related API: - -* {@link api/angular.directive Directive API} -* {@link api/angular.widget Widget API} diff --git a/docs/content/guide/dev_guide.compiler.directives_widgets.ngdoc b/docs/content/guide/dev_guide.compiler.directives_widgets.ngdoc deleted file mode 100644 index 1a0b1ad5..00000000 --- a/docs/content/guide/dev_guide.compiler.directives_widgets.ngdoc +++ /dev/null @@ -1,47 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Comparing Directives and Attribute Widgets -@description - -Although directives and {@link dev_guide.compiler.widgets attribute widgets} appear the same in a -template (`ng:init` is a directive, `ng:repeat` is an attribute widget), there is a difference in -the order in which they are evaluated.  The user of existing directives or widgets cannot determine -the order of evaluation. The evaluation order is the responsibility of the developer creating -custom directives and widgets. - -For example, consider this piece of HTML, which uses the `ng:repeat`, `ng:init`, and `ng:bind` -widget and directives: - -<pre> -<ul ng:init="people=['mike', 'mary']"> -<li ng:repeat="person in people" -    ng:init="a=a+1" -    ng:bind="person"> -</li> -</ul> -</pre> - -Notice that the order of execution matters here. Because we want to run the `ng:init="a=a+1` and -`ng:bind="person"` once for each `person in people`, we need to execute {@link -api/angular.widget.@ng:repeat ng:repeat} to make copies of the `<li>` element before we run the -{@link api/angular.directive.ng:init ng:init}, and {@link api/angular.directive.ng:bind ng:bind} -for each of the `<li>`copies. - -If you implemented `ng:repeat` as a directive, there would be no guarantee that the attributes -`ng:repeat`, `ng:init`, and `ng:bind` would be evaluated in the order they are declared, because -the order of element attributes in HTML is not significant to the browser. - -So, when creating a custom HTML attribute, you will have to consider whether a directive or a -widget is more appropriate. When the order of execution doesn't matter, directives are the right -choice. In a situation where the order matters and one attribute should be processed with a higher -priority than others, use a widget for the attribute that must be processed first. - - -## Related Topics - -* {@link dev_guide.compiler.directives Understanding Angular Directives} -* {@link dev_guide.compiler.widgets Understanding Angular Widgets} - -## Related API: - -* {@link api/angular.directive Directive API} -* {@link api/angular.widget Widget API} diff --git a/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc b/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc deleted file mode 100644 index 90c7f5e2..00000000 --- a/docs/content/guide/dev_guide.compiler.extending_compiler.ngdoc +++ /dev/null @@ -1,96 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Extending the Angular Compiler -@description - -Let's say that we want to create a new DOM element called `<my:greeter/>` that displays a greeting. -We want this HTML source: - -<pre> -   <div ng:init="s='Hello'; n='World'"> -      <my:greeter salutation="s" name="n"></my:greeter> -  </div> -</pre> - -to produce this DOM: - -<pre> -<div ng:init="s='Hello'; n='World'"> -<my:greeter salutation="s" name="n"/> -  <span class="salutation">Hello</span> -  <span class="name">World</span>! -</my:greeter> -</div> -</pre> - -That is, the new `<my:greeter></my:greeter>` tag's `salutation` and `name` attributes should be -transformed by the compiler such that two `<span>` tags display the values of the attributes, with -CSS classes applied to the output. - -The following code snippet shows how to write a following widget definition that will be processed -by the compiler. Note that you have to declare the {@link dev_guide.bootstrap namespace} `my` in -the page: - -<pre> -angular.widget('my:greeter', function(compileElement){ -  var compiler = this; -  compileElement.css('display', 'block'); -  var salutationExp = compileElement.attr('salutation'); -  var nameExp = compileElement.attr('name'); -  return function(linkElement){ -    var salutationSpan = angular.element('<span class="salutation"></span'); -    var nameSpan = angular.element('<span class="name"></span>'); -    linkElement.append(salutationSpan); -    linkElement.append(' '); -    linkElement.append(nameSpan); -    linkElement.append('!'); -    this.$watch(salutationExp, function(value){ -      salutationSpan.text(value); -     }); -    this.$watch(nameExp, function(value){ -    nameSpan.text(value); -    }); -  }; -}); -</pre> - - -Note: For more about widgets, see {@link dev_guide.compiler.widgets Understanding Angular Widgets} -and the {@link api/angular.widget widget API reference page}. - -# Compilation process for `<my:greeter>` - -Here are the steps that the compiler takes in processing the page that contains the widget -definition above: - -## Compile Phase - -1. Recursively traverse the DOM depth-first. -2. Find the angular.widget definition. -3. Find and execute the widget's compileElement function, which includes the following steps: -   1. Add a style element with attribute display: block; to the template DOM so that the browser -knows to treat the element as block element for rendering. (Note: because this style element was -added on the template compileElement, this style is automatically applied to any clones of the -template (i.e. any repeating elements)). -   2. Extract the salutation and name HTML attributes as angular expressions. -4. Return the aggregate link function, which includes just one link function in this example. - -## Link Phase - -1. Execute the aggregate link function, which includes the following steps: -   1. Create a <span> element set to the salutation class -   2. Create a <span> element set to the name class. -2. Add the span elements to the linkElement. (Note: be careful not to add them to the -compileElement, because that's the template.) -3. Set up watches on the expressions. When an expression changes, copy the data to the -corresponding spans. - - -## Related Topics - -* {@link dev_guide.compiler Angular HTML Compiler} -* {@link dev_guide.compiler.understanding_compiler Understanding How the Compiler Works} -* {@link dev_guide.compiler.testing_dom_element Testing a New DOM Element} - -## Related API - -* {@link api/angular.module.ng.$compile $compile()} diff --git a/docs/content/guide/dev_guide.compiler.markup.ngdoc b/docs/content/guide/dev_guide.compiler.markup.ngdoc deleted file mode 100644 index 0a01da57..00000000 --- a/docs/content/guide/dev_guide.compiler.markup.ngdoc +++ /dev/null @@ -1,92 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Understanding Angular Markup -@description - -Markup in angular is a feature that you can use in templates to transform the content of DOM -elements prior to the compile phase (in which elements are compiled and link functions are -returned.  See the {@link dev_guide.compiler compiler docs} for details on how the compiler -works.)  The ability to make pre-compile changes to DOM elements lets you create shorthand for -{@link api/angular.widget widget} and {@link api/angular.directive directive} declarations. - -Angular provides one built-in markup feature: the double curly-braces used to declare binding -points (between the model and view) for angular expressions.  You can also create your own custom -markup. - -# Using Double Curly-brace Markup (`{{ }}`) - -The double curly-brace (`{{ }}`) markup translates an enclosed expression into an {@link -api/angular.directive.ng:bind ng:bind} directive: - -<pre> -{{expression}} -</pre> - -is transformed to: - -<pre> -<span ng:bind="expression"></span> -</pre> - -Markup is useful for the simple reason that `{{1+2}}` is easier to write and understand than `<span -ng:bind="1+2"></span>`. After markup shorthand is expanded into the DOM elements it represents, the -expanded elements are then {@link dev_guide.compiler compiled} normally. - - -# Creating Custom Markup - -Let's say you want to define markup that transforms `---` into a horizontal rule (`<hr/>`): - -<pre> -header ---- -footer -</pre> - -should translate to: -<pre> -header -<hr/> -footer -</pre> - -Here is how you could extend the angular compiler to create the "---" markup: - -<pre> -angular.markup('---', function(text, textNode, parentElement) { -    var compiler = this; -    var index = text.indexOf('---'); -    if (index > -1) { -        textNode.after(text.substring(index + 3)); -        textNode.after(angular.element('<hr>')); -        textNode.after(text.substring(0, index)); -        textNode.remove(); -    } -}); -</pre> - -Unlike the way the compiler processes {@link api/angular.widget widgets} and {@link -api/angular.directive directives} (matching the name of the handler function to a DOM element or -attribute name), the compiler calls every markup handler for every text node, giving the handler a -chance to transform the text. The markup handler needs to find all the matches in the text. - -## Attribute Markup - -Attribute markup extends the angular compiler in a very similar way to markup, except that it -allows you to modify the state of attribute text rather then the content of a node. - -<pre> -angular.attrMarkup('extraClass', function(attrValue, attrName, element){ - if (attrName == 'additional-class') { -   element.addClass(attrValue); - } -}); -</pre> - - -## Related Topics - -* {@link dev_guide.compiler Angular HTML Compiler} - -## Related API - -* {@link api/angular.module.ng.$compile Compiler API Reference} diff --git a/docs/content/guide/dev_guide.compiler.ngdoc b/docs/content/guide/dev_guide.compiler.ngdoc index 2789c843..265b21db 100644 --- a/docs/content/guide/dev_guide.compiler.ngdoc +++ b/docs/content/guide/dev_guide.compiler.ngdoc @@ -2,8 +2,8 @@  @name Developer Guide: Angular HTML Compiler  @description -The core of angular is its HTML compiler.  The compiler processes angular directives, widgets, and -markup to transform a static HTML page into a dynamic web application. +The core of angular is its HTML compiler.  The compiler processes angular directives allowing them +to transform a static HTML page into a dynamic web application.  The default HTML transformations that the angular compiler provides are useful for building generic  apps, but you can also extend the compiler to create a domain-specific language for building @@ -15,12 +15,9 @@ All compilation takes place in the web browser; no server is involved.  ## Related Topics  * {@link dev_guide.compiler.understanding_compiler Understanding How the Compiler Works} -* {@link dev_guide.compiler.extending_compiler Extending the Angular Compiler}  * {@link dev_guide.compiler.testing_dom_element Testing a New DOM Element} -* {@link dev_guide.compiler.widgets Understanding Angular Widgets} -* {@link dev_guide.compiler.directives Understanding Angular Directives} -* {@link dev_guide.compiler.markup Understanding Angular Markup}  ## Related API  * {@link api/angular.module.ng.$compile Angular Compiler API} +* {@link api/angular.module.ng.$compileProvider.directive Directives API} diff --git a/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc b/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc index e077bf4d..8ffa760e 100644 --- a/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc +++ b/docs/content/guide/dev_guide.compiler.testing_dom_element.ngdoc @@ -10,7 +10,6 @@  * {@link dev_guide.compiler Angular HTML Compiler}  * {@link dev_guide.compiler.understanding_compiler Understanding How the Compiler Works} -* {@link dev_guide.compiler.extending_compiler Extending the Angular Compiler}  ## Related API diff --git a/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc b/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc index d5678be4..e802aee6 100644 --- a/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc +++ b/docs/content/guide/dev_guide.compiler.understanding_compiler.ngdoc @@ -2,59 +2,27 @@  @name Developer Guide: Angular HTML Compiler: Understanding How the Compiler Works  @description -Every {@link api/angular.widget widget}, {@link api/angular.directive directive} and {@link -dev_guide.compiler.markup markup} is defined with a compile function, which the angular compiler -executes on each widget or directive it encounters. The compile function optionally returns a link -function.  This compilation process happens automatically when the page is loaded when you specify -`ng:app` on the root element of the application.  (See {@link dev_guide.bootstrap Initializing Angular}.) - -The compile and link functions are related as follows: - -* **compile function** — Registers a listener for the widget, directive, or markup expression. The -compiler calls this function exactly once. -* **link function** — Sets up the listener registered by the compile function. This function can be -called multiple times, once per cloned DOM element. For example, in the case of the {@link -api/angular.widget.@ng:repeat repeater widget} used in a list element (`<li ng:repeat="[item in -dataset]"`), the link function gets called to set up a listener on each element in the list. - -Note that angular's built-in widgets, directives, and markup have predefined compile and link -functions that you don't need to modify. When you create your own widgets, directives, or markup, -you must write compile and link functions for them. Refer to the {@link api/angular.module.ng.$compile -Compiler API} for details. - -When the angular compiler compiles a page, it proceeds through 3 phases: Compile, Create Root -Scope, and Link: - -1. Compile Phase - -   1. Recursively traverse the DOM, depth-first. -   2. Look for a matching compile function of type widget, then markup, then directive. -   3. If a compile function is found then execute it. -   4. When the compile function completes, it should return a link function. Aggregate this link -function with all link functions returned previously by step 3. -   5. Repeat steps 3 and 4 for all compile functions found. - -The result of the compilation phase is an aggregate link function, which comprises all of the -individual link functions. - -2. Create Root Scope Phase - -* Inject all services into the root scope. - -3. Link Phase - -   1. Execute the aggregate link function with the root scope. The aggregate link function calls -all of the individual link functions that were generated in the compile phase. -   2. If there are any clones of the DOM caused by repeating elements, call the link function -multiple times, one for each repeating item. - -Note that while the compile function is executed exactly once, the link function can be executed -multiple times, for example, once for each iteration in a repeater. - -The angular compiler exposes methods that you will need to make use of when writing your own -widgets and directives.  For information on these methods, see the {@link api/angular.module.ng.$compile -Compiler API doc}. - +The {@link angular.module.ng.$compile compiler} is responsible for applying +{@link angular.module.ng.$compileProvider.directive directives} to the HTML. The directives +extend the behavior of HTML elements and can effect the DOM structure, presentation, and behavior. +This allows Angular to teach the browser new tricks. + +The compilation starts at the root element and proceeds in a depth-first order. As the compiler +visits each node it collects the directives, orders them by priority and executes their compile +function. The result of the compilation process is a linking function. The linking function +can be used on the template clones to quickly bind the directives with the scope. + +The result of the compilation process is a live view. We say 'live' since any changes to the +model attached to the {@link angular.module.ng.$rootScope.Scope scope} are reflected in the view, +and any changes in the view are reflected in the scope. This makes the scope the 'single source of +truth'. + +Since directives allow attachment of behavior to the HTML, the angular philosophy is to use the +HTML as Domain Specific Language (DSL) when building an application. For example it may be useful +to declare `TabPanel` directive, or `KeyboardShortcut` directive when for an application. + +For details on how directives are created see {@link angular.module.ng.$compileProvider.directive +directives}  ## Related Topics diff --git a/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc b/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc deleted file mode 100644 index 312f4000..00000000 --- a/docs/content/guide/dev_guide.compiler.widgets.creating_widgets.ngdoc +++ /dev/null @@ -1,95 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Widgets: Creating Custom Widgets -@description - -When you create your own widgets, you must set up your own namespace for them.  (See -dev_guide.bootstrap Initializing Angular} for information about namespaces in angular.) - -Let's say we would like to create a new element type in the namespace `my` that can watch an -expression and `alert()` the user with each new value: - -<pre> -// An element widget -<my:watch exp="name"></my:watch> -</pre> - -You can implement `my:watch` like this: - -<pre> -angular.widget('my:watch', function(compileElement) { - var compiler = this; - var exp = compileElement.attr('exp'); - return function(linkElement) { -   var currentScope = this; -   currentScope.$watch(exp, function(value){ -     alert(value); -   }); - }; -}); -</pre> - - -# Creating a Custom Attribute Widget - -Let's implement the same widget as in the example in Defining an Element Widget, but this time as -an attribute that can be added to any existing DOM element: - -<pre> -// An attribute widget (my:watch) in a div tag -<div my:watch="name">text</div> -</pre> -You can implement `my:watch` attribute like this: -<pre> -angular.widget('@my:watch', function(expression, compileElement) { -  var compiler = this; -  return function(linkElement) { -    var currentScope = this; -    currentScope.$watch(expression, function(value) { -      alert(value); -    }); -  }; -}); -</pre> - - -# Live Example of a Custom Element Widget - -<doc:example> -<doc:source> -<script> -angular.widget('my:time', function(compileElement){ -  compileElement.css('display', 'block'); -  return function(linkElement){ -    function update() { -      linkElement.text('Current time is: ' + new Date()); -      setTimeout(update, 1000); -    } -    update(); -  }; -}); -</script> -<my:time></my:time> -</doc:source> -<doc:scenario> -</doc:scenario> -</doc:example> - - -# Additional Compiler Methods for Custom Widgets - -The angular compiler exposes methods that you may need to use of when writing your own widgets and -directives.  For example, the `descend()` method lets you control whether the compiler ignores or -processes child elements of the element it is compiling.  For information on this and other -compiler methods, see the {@link api/angular.module.ng.$compile Compiler API doc}. - - -## Related Topics - -* {@link dev_guide.compiler Angular HTML Compiler} -* {@link dev_guide.compiler.directives Angular Directives} -* {@link dev_guide.compiler.widgets Angular Widgets} -* {@link dev_guide.compiler.directives.creating_directives Creating Custom Directives} - -## Related API - -* {@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.compiler.widgets.ngdoc b/docs/content/guide/dev_guide.compiler.widgets.ngdoc deleted file mode 100644 index 003cba53..00000000 --- a/docs/content/guide/dev_guide.compiler.widgets.ngdoc +++ /dev/null @@ -1,35 +0,0 @@ -@ngdoc overview -@name Developer Guide: Angular HTML Compiler: Understanding Angular Widgets -@description - -Widgets are DOM elements that the browser doesn't already understand. Angular provides some -built-in widgets (such as {@link api/angular.widget.@ng:repeat ng:repeat}), and you can create your -own custom widgets. - -Widgets are intended to manipulate the DOM tree by adding new elements (unlike {@link -dev_guide.compiler.directives angular directives}, which are intended to modify only element -properties). - -Widgets come in two types: - -* Element Widget — A custom DOM element.  An example of a custom element is shown in {@link -dev_guide.compiler.widgets.creating_widgets Creating Custom Widgets}. - -* Attribute Widget — A custom attribute on an existing DOM element.  An attribute widget is similar -to an angular directive, with the main difference being that an attribute widget will always be -processed before any directives that are specified on the same element.  Only one attribute widget -is allowed per element.  An example of an attribute widget is shown in {@link -dev_guide.compiler.widgets.creating_widgets Creating Custom Widgets}. - - - -## Related Topics - -* {@link dev_guide.compiler Angular HTML Compiler} -* {@link dev_guide.compiler.directives Angular Directives} -* {@link dev_guide.compiler.widgets.creating_widgets Creating Custom Widgets} -* {@link dev_guide.compiler.directives.creating_directives Creating Custom Directives} - -## Related API - -* {@link api/angular.module.ng.$compile Compiler API} diff --git a/docs/content/guide/dev_guide.expressions.ngdoc b/docs/content/guide/dev_guide.expressions.ngdoc index 61592897..08e7e60b 100644 --- a/docs/content/guide/dev_guide.expressions.ngdoc +++ b/docs/content/guide/dev_guide.expressions.ngdoc @@ -58,12 +58,8 @@ You can try evaluating different expressions here:          this.exprs.push(expr);       }; -     $scope.removeExp = function(contact) { -       for ( var i = 0, ii = this.exprs.length; i < ii; i++) { -         if (contact === this.exprs[i]) { -           this.exprs.splice(i, 1); -         } -       } +     $scope.removeExp = function(index) { +       this.exprs.splice(index, 1);       };     }   </script> @@ -73,7 +69,7 @@ You can try evaluating different expressions here:     <button ng:click="addExp(expr)">Evaluate</button>     <ul>      <li ng:repeat="expr in exprs"> -      [ <a href="" ng:click="removeExp(expr)">X</a> ] +      [ <a href="" ng:click="removeExp($index)">X</a> ]        <tt>{{expr}}</tt> => <span ng:bind="$parent.$eval(expr)"></span>       </li>     </ul> diff --git a/docs/content/guide/dev_guide.forms.ngdoc b/docs/content/guide/dev_guide.forms.ngdoc index c33596e6..5a6fe54e 100644 --- a/docs/content/guide/dev_guide.forms.ngdoc +++ b/docs/content/guide/dev_guide.forms.ngdoc @@ -17,7 +17,7 @@ Forms consist of all of the following:  # Form  A form groups a set of widgets together into a single logical data-set. A form is created using -the {@link api/angular.widget.form <form>} element that calls the +the {@link api/angular.module.ng.$compileProvider.directive.form <form>} element that calls the  {@link api/angular.module.ng.$formFactory $formFactory} service. The form is responsible for managing  the widgets and for tracking validation information. @@ -54,8 +54,8 @@ A form is:  # Widgets  In Angular, a widget is the term used for the UI with which the user input. Examples of -bult-in Angular widgets are {@link api/angular.widget.input input} and -{@link api/angular.widget.select select}. Widgets provide the rendering and the user +bult-in Angular widgets are {@link api/angular.module.ng.$compileProvider.directive.input input} and +{@link api/angular.module.ng.$compileProvider.directive.select select}. Widgets provide the rendering and the user  interaction logic. Widgets should be declared inside a form, if no form is provided an implicit  form {@link api/angular.module.ng.$formFactory $formFactory.rootForm} form is used. @@ -187,7 +187,7 @@ The following example demonstrates:       <hr/>       Debug View:       <pre>form={{form|json}}</pre> -     <pre>master={{master}|json}</pre> +     <pre>master={{master|json}}</pre>       <pre>userForm={{userForm|json}}</pre>       <pre>addressForm={{addressForm|json}}</pre>     </div> @@ -289,15 +289,15 @@ This example shows how to implement a custom HTML editor widget in Angular.              scope.$parseModel = function() {                // need to protect for script injection                try { -                this.$viewValue = $sanitize( -                  this.$modelValue || ''); +                scope.$viewValue = $sanitize( +                  scope.$modelValue || '');                  if (this.$error.HTML) {                    // we were invalid, but now we are OK. -                  this.$emit('$valid', 'HTML'); +                  scope.$emit('$valid', 'HTML');                  }                } catch (e) {                  // if HTML not parsable invalidate form. -                this.$emit('$invalid', 'HTML'); +                scope.$emit('$invalid', 'HTML');                }              } @@ -312,7 +312,7 @@ This example shows how to implement a custom HTML editor widget in Angular.              });            } -          angular.module.formModule = function($compileProvider){ +          angular.module('formModule', [], function($compileProvider){              $compileProvider.directive('ngHtmlEditorModel', function ($formFactory) {                return function(scope, element, attr) {                  var form = $formFactory.forElement(element), @@ -330,7 +330,7 @@ This example shows how to implement a custom HTML editor widget in Angular.                  });                };              }); -          }; +          });          </script>          <form name='editorForm' ng:controller="EditorCntl">            <div ng:html-editor-model="htmlContent"></div> diff --git a/docs/content/guide/dev_guide.i18n.ngdoc b/docs/content/guide/dev_guide.i18n.ngdoc index 1b9c1cde..1db13429 100644 --- a/docs/content/guide/dev_guide.i18n.ngdoc +++ b/docs/content/guide/dev_guide.i18n.ngdoc @@ -22,7 +22,7 @@ http://docs.angularjs.org/#!/api/angular.module.ng.$filter.number number} and {@  http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency} filters.  Additionally, Angular supports localizable pluralization support provided by the {@link -api/angular.widget.ng:pluralize ng:pluralize widget}. +api/angular.module.ng.$compileProvider.directive.ng:pluralize ng:pluralize widget}.  All localizable Angular components depend on locale-specific rule sets managed by the {@link  api/angular.module.ng.$locale $locale service}. diff --git a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc index 5f571680..c308e399 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc @@ -24,8 +24,8 @@ constructor). Constructors are always applied to an existing scope object.  You set up the initial state of a scope by creating model properties. For example: -function GreetingCtrl() { - this.greeting = 'Hola!'; +function GreetingCtrl($scope) { + $scope.greeting = 'Hola!';  }  The `GreetingCtrl` controller creates a `greeting` model which can be referred to in a template. @@ -43,7 +43,7 @@ As discussed in the {@link dev_guide.mvc.understanding_model Model} section of t  objects (or primitives) assigned to the scope become model properties. Any functions assigned to  the scope, along with any prototype methods of the controller type, become functions available in  the template/view, and can be invoked via angular expressions and `ng:` event handlers (e.g. {@link -api/angular.directive.ng:click ng:click}). These controller methods are always evaluated within the +api/angular.module.ng.$compileProvider.directive.ng:click ng:click}). These controller methods are always evaluated within the  context of the angular scope object that the controller function was applied to (which means that  the `this` keyword of any controller method is always bound to the scope that the controller  augments). This is how the second task of adding behavior to the scope is accomplished. @@ -78,7 +78,7 @@ instances).  # Associating Controllers with Angular Scope Objects  You can associate controllers with scope objects explicitly via the {@link api/angular.module.ng.$rootScope.Scope#$new -scope.$new} api or implicitly via the {@link api/angular.directive.ng:controller ng:controller +scope.$new} api or implicitly via the {@link api/angular.module.ng.$compileProvider.directive.ng:controller ng:controller  directive} or {@link api/angular.module.ng.$route $route service}. @@ -105,9 +105,9 @@ string "very". Depending on which button is clicked, the `spice` model is set to   <p>The food is {{spice}} spicy!</p>  </body> -function SpicyCtrl() { - this.spice = 'very'; - this.chiliSpicy = function() { +function SpicyCtrl($scope) { + $scope.spice = 'very'; + $scope.chiliSpicy = function() {     this.spice = 'chili';   }  } @@ -144,9 +144,9 @@ previous example.   <p>The food is {{spice}} spicy!</p>  </body> -function SpicyCtrl() { - this.spice = 'very'; - this.spicy = function(spice) { +function SpicyCtrl($scope) { + $scope.spice = 'very'; + $scope.spicy = function(spice) {     this.spice = spice;   }  } @@ -171,18 +171,18 @@ have a look at an example:     <p ng:controller="BabyCtrl">Good {{timeOfDay}}, {{name}}!</p>  </body> -function MainCtrl() { - this.timeOfDay = 'morning'; - this.name = 'Nikki'; +function MainCtrl($scope) { + $scope.timeOfDay = 'morning'; + $scope.name = 'Nikki';  } -function ChildCtrl() { - this.name = 'Mattie'; +function ChildCtrl($scope) { + $scope.name = 'Mattie';  } -function BabyCtrl() { - this.timeOfDay = 'evening'; - this.name = 'Gingerbreak Baby'; +function BabyCtrl($scope) { + $scope.timeOfDay = 'evening'; + $scope.name = 'Gingerbreak Baby';  }  </pre> diff --git a/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc index 3e037f1b..1e914c4b 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc @@ -20,17 +20,17 @@ following ways:  * Make a direct property assignment to the scope object in JavaScript code; this most commonly  occurs in controllers: -         function MyCtrl() { +         function MyCtrl($scope) {               // create property 'foo' on the MyCtrl's scope               // and assign it an initial value 'bar' -             this.foo = 'bar'; +             $scope.foo = 'bar';           }  * Use an {@link dev_guide.expressions angular expression} with an assignment operator in templates:           <button ng:click="{{foos='ball'}}">Click me</button> -* Use {@link api/angular.directive.ng:init ng:init directive} in templates (for toy/example apps +* Use {@link api/angular.module.ng.$compileProvider.directive.ng:init ng:init directive} in templates (for toy/example apps  only, not recommended for real applications):           <body ng:init=" foo = 'bar' "> @@ -45,7 +45,7 @@ when processing the following template constructs:     The code above creates a model called "query" on the current scope with the value set to "fluffy  cloud". -* An iterator declaration in {@link api/angular.widget.@ng:repeat ng:repeater}: +* An iterator declaration in {@link api/angular.module.ng.$compileProvider.directive.@ng:repeat ng:repeater}:           <p ng:repeat="phone in phones"></p> diff --git a/docs/content/guide/dev_guide.mvc.understanding_view.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_view.ngdoc index e313152b..5fd69dd1 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_view.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_view.ngdoc @@ -9,8 +9,8 @@ the DOM based on information in the template, controller and model.  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 {@link api/angular.directive.ng:controller -ng:controller} and {@link api/angular.widget.ng:view ng:view}, and through bindings of this form: +controller through angular directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng:controller +ng:controller} and {@link api/angular.module.ng.$compileProvider.directive.ng:view ng:view}, and through bindings of this form:  `{{someControllerFunction()}}`. In these ways, the view can call functions in an associated  controller function. diff --git a/docs/content/guide/dev_guide.overview.ngdoc b/docs/content/guide/dev_guide.overview.ngdoc index faf40af5..7f156f72 100644 --- a/docs/content/guide/dev_guide.overview.ngdoc +++ b/docs/content/guide/dev_guide.overview.ngdoc @@ -101,7 +101,7 @@ These input widgets look normal enough, but consider these points:  * When this page loaded, angular bound the names of the input widgets (`qty` and `cost`) to  variables of the same name. Think of those variables as the "Model" component of the  Model-View-Controller design pattern. -* Note the angular/HTML widget, {@link api/angular.widget.input input}. +* Note the angular/HTML widget, {@link api/angular.module.ng.$compileProvider.directive.input input}.  You may have noticed that when you enter invalid data  or leave the the input fields blank, the borders turn red color, and the display value disappears.  These widgets make it easier to implement field validation than coding them in JavaScript, @@ -113,7 +113,7 @@ And finally, the mysterious `{{ double curly braces }}`:  This notation, `{{ _expression_ }}`, is a bit of built-in angular {@link dev_guide.compiler.markup  markup}, a shortcut for displaying data to the user. The expression within curly braces gets -transformed by the angular compiler into an angular directive ({@link api/angular.directive.ng:bind +transformed by the angular compiler into an angular directive ({@link api/angular.module.ng.$compileProvider.directive.ng:bind  ng:bind}). The expression itself can be a combination of both an expression and a {@link  dev_guide.templates.filters filter}: `{{ expression | filter }}`. Angular provides filters for  formatting display data. diff --git a/docs/content/guide/dev_guide.scopes.internals.ngdoc b/docs/content/guide/dev_guide.scopes.internals.ngdoc index a81d8803..7cfac09a 100644 --- a/docs/content/guide/dev_guide.scopes.internals.ngdoc +++ b/docs/content/guide/dev_guide.scopes.internals.ngdoc @@ -46,11 +46,11 @@ reside on a child scope, if a property read does not find the property on a scop  recursively check the parent scope, grandparent scope, etc. all the way to the root scope before  defaulting to undefined. -{@link api/angular.directive Directives}  associated with elements (ng:controller, ng:repeat, -ng:include, etc.) create new child scopes that inherit properties from the current parent scope. -Any code in Angular is free to create a new scope. Whether or not your code does so is an -implementation detail of the directive, that is, you can decide when or if this happens. -Inheritance typically mimics HTML DOM element nesting, but does not do so with the same +{@link angular.module.ng.$compileProvider.directive directives} associated with elements +(ng:controller, ng:repeat, ng:include, etc.) create new child scopes that inherit properties from +the current parent scope. Any code in Angular is free to create a new scope. Whether or not your +code does so is an implementation detail of the directive, that is, you can decide when or if this +happens. Inheritance typically mimics HTML DOM element nesting, but does not do so with the same  granularity.  A property write will always write to the current scope. This means that a write can hide a parent @@ -117,24 +117,25 @@ scopes come into play throughout and get a sense of their interactions.  1. At application compile time, a root scope is created and is attached to the root `<HTML>` DOM  element.  2. During the compilation phase, the {@link dev_guide.compiler compiler} matches {@link -api/angular.directive directives} against the DOM template. The directives usually fall into one of -two categories: -   - Observing {@link api/angular.directive directives}, such as double-curly expressions -`{{expression}}`, register listeners using the {@link api/angular.module.ng.$rootScope.Scope#$watch $watch()} method. -This type of directive needs to be notified whenever the expression changes so that it can update -the view. -   -  Listener directives, such as {@link api/angular.directive.ng:click ng:click}, register a -listener with the DOM. When the DOM listener fires, the directive executes the associated -expression and updates the view using  the {@link api/angular.module.ng.$rootScope.Scope#$apply $apply()} method. +angular.module.ng.$compileProvider.directive directives} against the DOM template. The directives +usually fall into one of two categories: +   - Observing {@link angular.module.ng.$compileProvider.directive directives}, such as double-curly +    expressions `{{expression}}`, register listeners using the {@link +    api/angular.module.ng.$rootScope.Scope#$watch $watch()} method. This type of directive needs to +    be notified whenever the expression changes so that it can update the view. +   -  Listener directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng:click +   ng:click}, register a listener with the DOM. When the DOM listener fires, the directive executes +   the associated expression and updates the view using  the {@link +   api/angular.module.ng.$rootScope.Scope#$apply $apply()} method.  3. When an external event (such as a user action, timer or XHR) is received, the associated {@link  dev_guide.expressions expression} must be applied to the scope through the {@link  api/angular.module.ng.$rootScope.Scope#$apply $apply()} method so that all listeners are updated correctly.  ### Directives that create scopes -In most cases, {@link api/angular.directive directives} and scopes interact but do not create new -instances of scope. However, some directives, such as {@link api/angular.directive.ng:controller -ng:controller} and {@link api/angular.widget.@ng:repeat ng:repeat}, create new child scopes using +In most cases, {@link angular.module.ng.$compileProvider.directive directives} and scopes interact but do not create new +instances of scope. However, some directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng:controller +ng:controller} and {@link api/angular.module.ng.$compileProvider.directive.@ng:repeat ng:repeat}, create new child scopes using  the {@link api/angular.module.ng.$rootScope.Scope#$new $new()} method and then attach the child scope to the  corresponding DOM element. You can retrieve a scope for any DOM element by using an  `angular.element(aDomElement).scope()` method call.) @@ -143,7 +144,7 @@ corresponding DOM element. You can retrieve a scope for any DOM element by using  ### Controllers and scopes  Scopes and controllers interact with each other in the following situations:     - Controllers use scopes to expose controller methods to templates (see {@link -api/angular.directive.ng:controller ng:controller}). +api/angular.module.ng.$compileProvider.directive.ng:controller ng:controller}).     - Controllers define methods (behavior) that can mutate the model (properties on the scope).     - Controllers may register {@link api/angular.module.ng.$rootScope.Scope#$watch watches} on the model. These watches  execute immediately after the controller behavior executes, but before the DOM gets updated. @@ -169,7 +170,7 @@ $watch-ers firing and view getting updated. Similarly, when a request to fetch d  is made and the response comes back, the data is written into the model (scope) within an $apply,  which then pushes updates through to the view and any other dependents. -A widget that creates scopes (such as {@link api/angular.widget.@ng:repeat ng:repeat}) via `$new`, +A widget that creates scopes (such as {@link api/angular.module.ng.$compileProvider.directive.@ng:repeat ng:repeat}) via `$new`,  doesn't need to worry about propagating the `$digest` call from the parent scope to child scopes.  This happens automatically. diff --git a/docs/content/guide/dev_guide.scopes.ngdoc b/docs/content/guide/dev_guide.scopes.ngdoc index 7b9b77ec..f37dc34e 100644 --- a/docs/content/guide/dev_guide.scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.ngdoc @@ -14,7 +14,7 @@ the contexts in which Angular creates data-bindings between the model and the vi  In addition to providing the context in which data is evaluated, Angular scope objects watch for  model changes. The scope objects also notify all components interested in any model changes (for  example, functions registered through {@link api/angular.module.ng.$rootScope.Scope#$watch $watch}, bindings created by -{@link api/angular.directive.ng:bind ng:bind}, or HTML input elements). +{@link api/angular.module.ng.$compileProvider.directive.ng:bind ng:bind}, or HTML input elements).  Angular scope objects: diff --git a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc index 77f589dc..2c81dfa8 100644 --- a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc @@ -45,7 +45,7 @@ code, observe how the value of `name` changes, based on the HTML element it is d  </doc:scenario>  </doc:example> -The angular {@link api/angular.widget.@ng:repeat ng:repeat} directive creates a new scope for each +The angular {@link api/angular.module.ng.$compileProvider.directive.@ng:repeat ng:repeat} directive creates a new scope for each  element that it repeats (in this example the elements are list items). In the `<ul>` element, we  initialized `name` to "Hank", and we created an array called `names` to use as the data source for  the list items. In each `<li>` element, `name` is overridden. Outside of the `<li>` repeater, the diff --git a/docs/content/guide/dev_guide.services.$location.ngdoc b/docs/content/guide/dev_guide.services.$location.ngdoc index 2afbf1d2..f81bc599 100644 --- a/docs/content/guide/dev_guide.services.$location.ngdoc +++ b/docs/content/guide/dev_guide.services.$location.ngdoc @@ -434,40 +434,40 @@ In this examples we use `<base href="/base/index.html" />`      this.$location = $location;    } -  angular.widget('ng:address-bar', function(tpl) { -    return function(elm) { -      var browser = browsers[elm.attr('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()); -      } -    }; -  }); -    function initEnv(name) {      var root = angular.element(document.getElementById(name + '-mode')); -    angular.bootstrap(root, [function($locationProvider, $provide){ +    angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){        $locationProvider.html5Mode = true;        $locationProvider.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(); diff --git a/docs/content/guide/dev_guide.templates.css-styling.ngdoc b/docs/content/guide/dev_guide.templates.css-styling.ngdoc index 30571976..11eba2d1 100644 --- a/docs/content/guide/dev_guide.templates.css-styling.ngdoc +++ b/docs/content/guide/dev_guide.templates.css-styling.ngdoc @@ -9,24 +9,13 @@ Angular sets these CSS classes. It is up to your application to provide useful s  * `ng-invalid`, `ng-valid`    - **Usage:** angular applies this class to an input widget element if that element's input does -    notpass validation. (see {@link api/angular.widget.input input} widget). +    notpass validation. (see {@link api/angular.module.ng.$compileProvider.directive.input input} widget).  * `ng-pristine`, `ng-dirty` -  - **Usage:** angular {@link api/angular.widget.input input} widget applies `ng-pristine` class +  - **Usage:** angular {@link api/angular.module.ng.$compileProvider.directive.input input} widget applies `ng-pristine` 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 `ng-dirty`. -# Marking CSS classes - -* `ng-widget`, `ng-directive` -  -  **Usage:** angular sets these class on elements where {@link api/angular.widget widget} or -     {@link api/angular.directive directive} has bound to. - - -* Old browser support -  - Pre v9, IE browsers could not select `ng:include` elements in CSS, because of the `:` -    character. For this reason angular also sets `ng-include` class on any element which has `:` -    character in the name by replacing `:` with `-`.  ## Related Topics diff --git a/docs/content/guide/dev_guide.templates.ngdoc b/docs/content/guide/dev_guide.templates.ngdoc index 561773f1..2f62e89a 100644 --- a/docs/content/guide/dev_guide.templates.ngdoc +++ b/docs/content/guide/dev_guide.templates.ngdoc @@ -13,7 +13,7 @@ These are the types of angular elements and element attributes you can use in a  * {@link dev_guide.compiler.directives Directive} — An attribute that augments an existing DOM  element.  * {@link dev_guide.compiler.widgets Widget} — A custom DOM element. An example of a built-in widget -is {@link api/angular.widget.@ng:repeat ng:repeat}. +is {@link api/angular.module.ng.$compileProvider.directive.@ng:repeat ng:repeat}.  * {@link dev_guide.compiler.markup  Markup} — Shorthand for a widget or a directive. The double  curly brace notation `{{ }}` to bind expressions to elements is built-in angular markup.  * {@link dev_guide.templates.filters Filter} — Formats your data for display to the user. @@ -44,7 +44,7 @@ In a simple single-page app, the template consists of HTML, CSS, and angular dir  in just one HTML file (usually `index.html`). 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 {@link api/angular.module.ng.$route -$route} service in conjunction with the {@link api/angular.widget.ng:view ng:view} directive. An +$route} service in conjunction with the {@link api/angular.module.ng.$compileProvider.directive.ng:view ng:view} directive. An  example of this technique is shown in the {@link tutorial/ angular tutorial}, in steps seven and  eight. diff --git a/docs/content/misc/started.ngdoc b/docs/content/misc/started.ngdoc index 08e37668..e86b809b 100644 --- a/docs/content/misc/started.ngdoc +++ b/docs/content/misc/started.ngdoc @@ -78,8 +78,8 @@ After the refresh, the page should look something like this:  These are some of the important points to note from this example: -* The text input {@link api/angular.widget widget} called `yourname` is bound to a model variable -called `yourname`. +* The text input {@link api/angular.module.ng.$compileProvider.directive directive} +  is bound to a model variable called `yourname`.  * The double curly braces notation binds the `yourname` model to the greeting text.  * You did not need to explicitly register an event listener or define an event handler for events! diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index 8f109e92..c6f17628 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -154,13 +154,12 @@ describe('ngdoc', function() {            };          } -        var angular_widget = doc('overview', 'angular.widget'); -        var angular_x = doc('function', 'angular.x'); -        var angular_y = doc('property', 'angular.y'); +        var dev_guide_overview = doc('overview', 'dev_guide.overview'); +        var dev_guide_bootstrap = doc('function', 'dev_guide.bootstrap'); -        it('should put angular.fn() in front of angular.widget, etc', function() { -          expect(ngdoc.metadata([angular_widget, angular_y, angular_x]).map(property('id'))) -            .toEqual(['angular.x', 'angular.y', 'angular.widget' ]); +        it('should put angular.fn() in front of dev_guide.overview, etc', function() { +          expect(ngdoc.metadata([dev_guide_overview, dev_guide_bootstrap]).map(property('id'))) +            .toEqual(['dev_guide.overview', 'dev_guide.bootstrap']);          });        });      }); diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index 49c6607b..e39cb362 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -630,7 +630,6 @@ var KEYWORD_PRIORITY = {    '.angular.module': 8,    '.angular.mock': 9,    '.angular.module.ng.$filter': 7, -  '.angular.module.ng.$filter': 7,    '.angular.module.ng.$rootScope.Scope': 7,    '.angular.module.ng': 7,    '.angular.mock': 8, diff --git a/docs/src/templates/doc_widgets.js b/docs/src/templates/doc_widgets.js index bee59234..76ccac7f 100644 --- a/docs/src/templates/doc_widgets.js +++ b/docs/src/templates/doc_widgets.js @@ -27,7 +27,7 @@ angular.module('ngdocs.directives', [], function($compileProvider) {      return {        terminal: true,        compile: function(element, attrs) { -        var module = element.attr('module') || ''; +        var module = attrs.module;          //jQuery find() methods in this widget contain primitive selectors on purpose so that we can use          //jqlite instead. jqlite's find() method currently supports onlt getElementsByTagName! @@ -86,6 +86,17 @@ angular.module('ngdocs.directives', [], function($compileProvider) {              function($provide) {                $provide.value('$browser', $browser);                $provide.value('$location', $location); +              $provide.decorator('$defer', function($rootScope, $delegate) { +                return angular.extend(function(fn, delay) { +                  if (delay && delay > 500) { +                    return setTimeout(function() { +                      $rootScope.$apply(fn); +                    }, delay); +                  } else { +                    return $delegate.apply(this, arguments); +                  } +                }, $delegate); +              });              }            ];            module && modules.push(module); | 
