aboutsummaryrefslogtreecommitdiffstats
path: root/docs/content/api
diff options
context:
space:
mode:
authorMisko Hevery2011-04-29 15:18:27 -0700
committerIgor Minar2011-06-06 22:28:38 -0700
commit11e9572b952e49b01035e956c412d6095533031a (patch)
tree04dbf96802f552693d44c541c0d825a2769e3d57 /docs/content/api
parentb6bc6c2ddf1ae1523ec7e4cb92db209cd6501181 (diff)
downloadangular.js-11e9572b952e49b01035e956c412d6095533031a.tar.bz2
Move documentation under individual headings
Diffstat (limited to 'docs/content/api')
-rw-r--r--docs/content/api/angular.attrMarkup.ngdoc15
-rw-r--r--docs/content/api/angular.directive.ngdoc53
-rw-r--r--docs/content/api/angular.element.ngdoc49
-rw-r--r--docs/content/api/angular.filter.ngdoc87
-rw-r--r--docs/content/api/angular.formatter.ngdoc82
-rw-r--r--docs/content/api/angular.markup.ngdoc66
-rw-r--r--docs/content/api/angular.ngdoc4
-rw-r--r--docs/content/api/angular.service.ngdoc175
-rw-r--r--docs/content/api/angular.validator.ngdoc77
-rw-r--r--docs/content/api/angular.widget.ngdoc78
10 files changed, 686 insertions, 0 deletions
diff --git a/docs/content/api/angular.attrMarkup.ngdoc b/docs/content/api/angular.attrMarkup.ngdoc
new file mode 100644
index 00000000..aad20866
--- /dev/null
+++ b/docs/content/api/angular.attrMarkup.ngdoc
@@ -0,0 +1,15 @@
+@workInProgress
+@ngdoc overview
+@name angular.attrMarkup
+
+@description
+Attribute markup extends the angular compiler in a very similar way as {@link angular.markup} except
+that it allows you to modify the state of the 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>
diff --git a/docs/content/api/angular.directive.ngdoc b/docs/content/api/angular.directive.ngdoc
new file mode 100644
index 00000000..9a08e4c7
--- /dev/null
+++ b/docs/content/api/angular.directive.ngdoc
@@ -0,0 +1,53 @@
+@workInProgress
+@ngdoc overview
+@name angular.directive
+@namespace Namespace for all directives.
+
+@description
+A directive is an HTML attribute that you can use in an existing HTML element type or in a
+DOM element type that you create as {@link angular.widget}, to modify that element's
+properties. You can use any number of directives per element.
+
+For example, you can add the ng:bind directive as an attribute of an HTML span element, as in
+`<span ng:bind="1+2"></span>`. How does this work? The compiler passes the attribute value
+`1+2` to the ng:bind extension, which in turn tells the {@link angular.scope} to watch that
+expression and report changes. On any change it sets the span text to the expression value.
+
+Here's how to define {@link angular.directive.ng:bind ng:bind}:
+<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>
+
+# Directive vs. Attribute Widget
+Both [attribute widgets](#!angular.widget) and directives can compile a DOM element
+attribute. So why have two different ways to do the same thing? The answer is that order
+matters, but we have no control over the order in which attributes are read. To solve this
+we apply attribute widget before the directive.
+
+For example, consider this piece of HTML, which uses the directives `ng:repeat`, `ng:init`,
+and `ng:bind`:
+<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. We need to execute
+{@link angular.directive.ng:repeat ng:repeat} before we run the
+{@link angular.directive.ng:init ng:init} and `ng:bind` on the `<li/>;`. This is because we
+want to run the `ng:init="a=a+1` and `ng:bind="person"` once for each person in people. We
+could not have used directive to create this template because attributes are read in an
+unspecified order and there is no way of guaranteeing that the repeater attribute would
+execute first. Using the `ng:repeat` attribute directive ensures that we can transform the
+DOM element into a template.
+
+Widgets run before directives. Widgets may manipulate the DOM whereas directives are not
+expected to do so, and so they run last.
diff --git a/docs/content/api/angular.element.ngdoc b/docs/content/api/angular.element.ngdoc
new file mode 100644
index 00000000..2ce007fd
--- /dev/null
+++ b/docs/content/api/angular.element.ngdoc
@@ -0,0 +1,49 @@
+@workInProgress
+@ngdoc function
+@name angular.element
+@function
+
+@description
+Wraps a raw DOM element or HTML string as [jQuery](http://jquery.com) element.
+`angular.element` is either an alias for [jQuery](http://api.jquery.com/jQuery/) function if
+jQuery is loaded or a function that wraps the element or string in angular's jQuery lite
+implementation.
+
+Real jQuery always takes precedence (as long as it was loaded before `DOMContentEvent`)
+
+Angular's jQuery lite implementation is a tiny API-compatible subset of jQuery which allows
+angular to manipulate DOM. The jQuery lite implements only a subset of jQuery api, with the
+focus on the most commonly needed functionality and minimal footprint. For this reason only a
+limited number of jQuery methods, arguments and invocation styles are supported.
+
+NOTE: All element references in angular are always wrapped with jQuery (lite) and are never
+raw DOM references.
+
+## Angular's jQuery lite implements these functions:
+
+- [addClass()](http://api.jquery.com/addClass/)
+- [after()](http://api.jquery.com/after/)
+- [append()](http://api.jquery.com/append/)
+- [attr()](http://api.jquery.com/attr/)
+- [bind()](http://api.jquery.com/bind/)
+- [children()](http://api.jquery.com/children/)
+- [clone()](http://api.jquery.com/clone/)
+- [css()](http://api.jquery.com/css/)
+- [data()](http://api.jquery.com/data/)
+- [hasClass()](http://api.jquery.com/hasClass/)
+- [parent()](http://api.jquery.com/parent/)
+- [remove()](http://api.jquery.com/remove/)
+- [removeAttr()](http://api.jquery.com/removeAttr/)
+- [removeClass()](http://api.jquery.com/removeClass/)
+- [removeData()](http://api.jquery.com/removeData/)
+- [replaceWith()](http://api.jquery.com/replaceWith/)
+- [text()](http://api.jquery.com/text/)
+- [trigger()](http://api.jquery.com/trigger/)
+
+## Additionally these methods extend the jQuery and are available in both jQuery and jQuery lite
+version:
+
+- `scope()` - retrieves the current angular scope of the element.
+
+@param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+@returns {Object} jQuery object.
diff --git a/docs/content/api/angular.filter.ngdoc b/docs/content/api/angular.filter.ngdoc
new file mode 100644
index 00000000..5d4f5940
--- /dev/null
+++ b/docs/content/api/angular.filter.ngdoc
@@ -0,0 +1,87 @@
+@workInProgress
+@ngdoc overview
+@name angular.filter
+@namespace Namespace for all filters.
+@description
+# Overview
+Filters are a standard way to format your data for display to the user. For example, you
+might have the number 1234.5678 and would like to display it as US currency: $1,234.57.
+Filters allow you to do just that. In addition to transforming the data, filters also modify
+the DOM. This allows the filters to for example apply css styles to the filtered output if
+certain conditions were met.
+
+
+# Standard Filters
+
+The Angular framework provides a standard set of filters for common operations, including:
+{@link angular.filter.currency currency}, {@link angular.filter.json json},
+{@link angular.filter.number number}, and {@link angular.filter.html html}. You can also add
+your own filters.
+
+
+# Syntax
+
+Filters can be part of any {@link angular.scope} evaluation but are typically used with
+{{bindings}}. Filters typically transform the data to a new data type, formating the data in
+the process. Filters can be chained and take optional arguments. Here are few examples:
+
+* No filter: {{1234.5678}} => 1234.5678
+* Number filter: {{1234.5678|number}} => 1,234.57. Notice the “,” and rounding to two
+ significant digits.
+* Filter with arguments: {{1234.5678|number:5}} => 1,234.56780. Filters can take optional
+ arguments, separated by colons in a binding. To number, the argument “5” requests 5 digits
+ to the right of the decimal point.
+
+
+# Writing your own Filters
+
+Writing your own filter is very easy: just define a JavaScript function on `angular.filter`.
+The framework passes in the input value as the first argument to your function. Any filter
+arguments are passed in as additional function arguments.
+
+You can use these variables in the function:
+
+* `this` — The current scope.
+* `this.$element` — The DOM element containing the binding. This allows the filter to manipulate
+ the DOM in addition to transforming the input.
+
+
+@example
+ The following example filter reverses a text string. In addition, it conditionally makes the
+ text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM
+ modification).
+
+<doc:example>
+ <doc:source>
+ <script type="text/javascript">
+ angular.filter('reverse', function(input, uppercase, color) {
+ var out = "";
+ for (var i = 0; i < input.length; i++) {
+ out = input.charAt(i) + out;
+ }
+ if (uppercase) {
+ out = out.toUpperCase();
+ }
+ if (color) {
+ this.$element.css('color', color);
+ }
+ return out;
+ });
+ </script>
+
+ <input name="text" type="text" value="hello" /><br>
+ No filter: {{text}}<br>
+ Reverse: {{text|reverse}}<br>
+ Reverse + uppercase: {{text|reverse:true}}<br>
+ Reverse + uppercase + blue: {{text|reverse:true:"blue"}}
+ </doc:source>
+ <doc:scenario>
+ it('should reverse text', function(){
+ expect(binding('text|reverse')).toEqual('olleh');
+ input('text').enter('ABC');
+ expect(binding('text|reverse')).toEqual('CBA');
+ });
+ </doc:scenario>
+</doc:example>
+
+
diff --git a/docs/content/api/angular.formatter.ngdoc b/docs/content/api/angular.formatter.ngdoc
new file mode 100644
index 00000000..4eef190e
--- /dev/null
+++ b/docs/content/api/angular.formatter.ngdoc
@@ -0,0 +1,82 @@
+@workInProgress
+@ngdoc overview
+@name angular.formatter
+@namespace Namespace for all formats.
+@description
+# Overview
+The formatters are responsible for translating user readable text in an input widget to a
+data model stored in an application.
+
+# Writting your own Formatter
+Writing your own formatter is easy. Just register a pair of JavaScript functions with
+`angular.formatter`. One function for parsing user input text to the stored form,
+and one for formatting the stored data to user-visible text.
+
+Here is an example of a "reverse" formatter: The data is stored in uppercase and in
+reverse, while it is displayed in lower case and non-reversed. User edits are
+automatically parsed into the internal form and data changes are automatically
+formatted to the viewed form.
+
+<pre>
+function reverse(text) {
+ var reversed = [];
+ for (var i = 0; i < text.length; i++) {
+ reversed.unshift(text.charAt(i));
+ }
+ return reversed.join('');
+}
+
+angular.formatter('reverse', {
+ parse: function(value){
+ return reverse(value||'').toUpperCase();
+ },
+ format: function(value){
+ return reverse(value||'').toLowerCase();
+ }
+});
+</pre>
+
+@example
+<doc:example>
+ <doc:source>
+ <script type="text/javascript">
+ function reverse(text) {
+ var reversed = [];
+ for (var i = 0; i < text.length; i++) {
+ reversed.unshift(text.charAt(i));
+ }
+ return reversed.join('');
+ }
+
+ angular.formatter('reverse', {
+ parse: function(value){
+ return reverse(value||'').toUpperCase();
+ },
+ format: function(value){
+ return reverse(value||'').toLowerCase();
+ }
+ });
+ </script>
+
+ Formatted:
+ <input type="text" name="data" value="angular" ng:format="reverse"/>
+ <br/>
+
+ Stored:
+ <input type="text" name="data"/><br/>
+ <pre>{{data}}</pre>
+ </doc:source>
+ <doc:scenario>
+ it('should store reverse', function(){
+ expect(element('.doc-example-live input:first').val()).toEqual('angular');
+ expect(element('.doc-example-live input:last').val()).toEqual('RALUGNA');
+
+ this.addFutureAction('change to XYZ', function($window, $document, done){
+ $document.elements('.doc-example-live input:last').val('XYZ').trigger('change');
+ done();
+ });
+ expect(element('.doc-example-live input:first').val()).toEqual('zyx');
+ });
+ </doc:scenario>
+</doc:example>
+
diff --git a/docs/content/api/angular.markup.ngdoc b/docs/content/api/angular.markup.ngdoc
new file mode 100644
index 00000000..a40385c8
--- /dev/null
+++ b/docs/content/api/angular.markup.ngdoc
@@ -0,0 +1,66 @@
+@workInProgress
+@ngdoc overview
+@name angular.markup
+
+@description
+#Overview
+Markups allow the angular compiler to transform content of DOM elements or portions of this content
+into other text or DOM elements for further compilation. Markup extensions do not themselves produce
+linking functions. Think of markup as a way to produce shorthand for a {@link angular.widget widget}
+ or a {@link angular.directive directive}.
+
+#`{{}}` (double curly) built-in markup
+`{{}}` markup is a built-in markup, which translates the enclosed expression into an
+{@link angular.directive.ng:bind ng:bind} directive. It simply transforms
+
+<pre>
+{{expression}}
+</pre>
+
+to:
+
+<pre>
+<span ng:bind="expression"></span>
+</pre>
+
+For example `{{1+2}}` is easier to write and understand than `<span ng:bind="1+2"></span>`. The
+expanded elements are then {@link guide.compiler compiled} normally.
+
+# Custom markup
+Let's say you want to define this shorthand for a horizontal rule: `---` for `<hr/>`.
+
+In other words, this HTML:
+<pre>
+header
+---
+footer
+</pre>
+
+should translate to:
+<pre>
+header
+<hr/>
+footer
+</pre>
+
+Here's how the angular compiler could be extended to achieve this:
+<pre>
+angular.markup('---', function(text, textNode, parentElement) {
+ var compiler = this;
+ var index = text.indexOf('---');
+ if (index > -1) {
+ var before = compiler.text(text.substring(0, index));
+ var hr = compiler.element('hr');
+ var after = compiler.text(text.substring(index + 3));
+ textNode.after(after);
+ textNode.after(hr);
+ textNode.after(before);
+ textNode.remove();
+ }
+});
+</pre>
+
+Unlike {@link angular.widget widgets} and {@link angular.directive directives}, in which the
+compiler matches the name of handler function to a DOM element or attribute name, for markup 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.
diff --git a/docs/content/api/angular.ngdoc b/docs/content/api/angular.ngdoc
new file mode 100644
index 00000000..3f342d1b
--- /dev/null
+++ b/docs/content/api/angular.ngdoc
@@ -0,0 +1,4 @@
+@workInProgress
+@ngdoc overview
+@name angular
+@namespace The exported angular namespace.
diff --git a/docs/content/api/angular.service.ngdoc b/docs/content/api/angular.service.ngdoc
new file mode 100644
index 00000000..0d3406e5
--- /dev/null
+++ b/docs/content/api/angular.service.ngdoc
@@ -0,0 +1,175 @@
+@workInProgress
+@ngdoc overview
+@name angular.service
+
+@description
+# Overview
+Services are substituable objects, which are wired together using dependency injection (DI).
+Each service could have dependencies (other services), which are passed in constructor.
+Because JS is dynamicaly typed language, dependency injection can not use static types
+to identify these dependencies, so each service must explicitely define its dependencies.
+This is done by `$inject` property.
+
+
+# Built-in services
+angular provides a set of services for common operations. These services can be overriden by custom
+services if needed.
+
+Like other core angular variables and identifiers, the built-in services always start with `$`.
+
+ * {@link angular.service.$browser $browser}
+ * {@link angular.service.$window $window}
+ * {@link angular.service.$document $document}
+ * {@link angular.service.$location $location}
+ * {@link angular.service.$log $log}
+ * {@link angular.service.$exceptionHandler $exceptionHandler}
+ * {@link angular.service.$hover $hover}
+ * {@link angular.service.$invalidWidgets $invalidWidgets}
+ * {@link angular.service.$route $route}
+ * {@link angular.service.$xhr $xhr}
+ * {@link angular.service.$xhr.error $xhr.error}
+ * {@link angular.service.$xhr.bulk $xhr.bulk}
+ * {@link angular.service.$xhr.cache $xhr.cache}
+ * {@link angular.service.$resource $resource}
+ * {@link angular.service.$cookies $cookies}
+ * {@link angular.service.$cookieStore $cookieStore}
+
+# Writing your own custom services
+angular provides only set of basic services, so for any nontrivial application it will be necessary
+to write one or more custom services. To do so, a factory function that creates a services needs to
+be registered with angular's dependency injector. This factory function must return an object - the
+service (it is not called with the `new` operator).
+
+**angular.service** accepts three parameters:
+
+ - `{string} name` - Name of the service.
+ - `{function()} factory` - Factory function (called just once by DI).
+ - `{Object} config` - Configuration object with following properties:
+ - `$inject` - {Array.<string>} - Array of service ids that this service depends on. These
+ services will be passed as arguments into the factory function in the same order as specified
+ in the `$inject` array. Defaults to `[]`.
+ - `$eager` - {boolean} - If true, the service factory will be called and thus, the service will
+ be instantiated when angular boots. If false, service will be lazily instantiated when it is
+ first requested during instantiation of a dependant. Defaults to `false`.
+
+The `this` of the factory function is bound to the root scope of the angular application.
+
+angular enables services to participate in dependency injection (DI) by registering themselves with
+angular's DI system (injector) under a `name` (id) as well as by declaring dependencies which need
+to be provided for the factory function of the registered service. The ability to swap dependencies
+for mocks/stubs/dummies in tests allows for services to be highly testable.
+
+Here is an example of very simple service. This service requires $window service (it's
+passed as a parameter to factory function) and it's just a function.
+
+This service simple stores all notifications and after third one, it displays all of them by
+window alert.
+<pre>
+ angular.service('notify', function(win) {
+ var msgs = [];
+ return function(msg) {
+ msgs.push(msg);
+ if (msgs.length == 3) {
+ win.alert(msgs.join("\n"));
+ msgs = [];
+ }
+ };
+ }, {$inject: ['$window']});
+</pre>
+
+And here is a unit test for this service. We use Jasmine spy (mock) instead of real browser's alert.
+<pre>
+var mock, notify;
+
+beforeEach(function() {
+ mock = {alert: jasmine.createSpy()};
+ notify = angular.service('notify')(mock);
+});
+
+it('should not alert first two notifications', function() {
+ notify('one');
+ notify('two');
+ expect(mock.alert).not.toHaveBeenCalled();
+});
+
+it('should alert all after third notification', function() {
+ notify('one');
+ notify('two');
+ notify('three');
+ expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
+});
+
+it('should clear messages after alert', function() {
+ notify('one');
+ notify('two');
+ notify('third');
+ notify('more');
+ notify('two');
+ notify('third');
+ expect(mock.alert.callCount).toEqual(2);
+ expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]);
+});
+</pre>
+
+# Injecting services into controllers
+Using services as dependencies for controllers is very similar to using them as dependencies for
+another service.
+
+JavaScript is dynamic language, so DI is not able to figure out which services to inject by
+static types (like in static typed languages). Therefore you must specify the service name
+by the `$inject` property - it's an array that contains strings with names of services to be
+injected. The name must match the id that service has been registered as with angular.
+The order of the services in the array matters, because this order will be used when calling
+the factory function with injected parameters. The names of parameters in factory function
+don't matter, but by convention they match the service ids.
+<pre>
+function myController($loc, $log) {
+ this.firstMethod = function() {
+ // use $location service
+ $loc.setHash();
+ };
+ this.secondMethod = function() {
+ // use $log service
+ $log.info('...');
+ };
+}
+// which services to inject ?
+myController.$inject = ['$location', '$log'];
+</pre>
+
+@example
+<doc:example>
+ <doc:source>
+ <script type="text/javascript">
+ angular.service('notify', function(win) {
+ var msgs = [];
+ return function(msg) {
+ msgs.push(msg);
+ if (msgs.length == 3) {
+ win.alert(msgs.join("\n"));
+ msgs = [];
+ }
+ };
+ }, {$inject: ['$window']});
+
+ function myController(notifyService) {
+ this.callNotify = function(msg) {
+ notifyService(msg);
+ };
+ }
+
+ myController.$inject = ['notify'];
+ </script>
+
+ <div ng:controller="myController">
+ <p>Let's try this simple notify service, injected into the controller...</p>
+ <input ng:init="message='test'" type="text" name="message" />
+ <button ng:click="callNotify(message);">NOTIFY</button>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ it('should test service', function(){
+ expect(element(':input[name=message]').val()).toEqual('test');
+ });
+ </doc:scenario>
+</doc:example>
diff --git a/docs/content/api/angular.validator.ngdoc b/docs/content/api/angular.validator.ngdoc
new file mode 100644
index 00000000..96b1e76a
--- /dev/null
+++ b/docs/content/api/angular.validator.ngdoc
@@ -0,0 +1,77 @@
+@workInProgress
+@ngdoc overview
+@name angular.validator
+@namespace Namespace for all filters.
+@description
+# Overview
+Validators are a standard way to check the user input against a specific criteria. For
+example, you might need to check that an input field contains a well-formed phone number.
+
+# Syntax
+Attach a validator on user input widgets using the `ng:validate` attribute.
+
+<doc:example>
+ <doc:source>
+ Change me: <input type="text" name="number" ng:validate="integer" value="123">
+ </doc:source>
+ <doc:scenario>
+ it('should validate the default number string', function() {
+ expect(element('input[name=number]').attr('class')).
+ not().toMatch(/ng-validation-error/);
+ });
+ it('should not validate "foo"', function() {
+ input('number').enter('foo');
+ expect(element('input[name=number]').attr('class')).
+ toMatch(/ng-validation-error/);
+ });
+ </doc:scenario>
+</doc:example>
+
+
+# Writing your own Validators
+Writing your own validator is easy. To make a function available as a
+validator, just define the JavaScript function on the `angular.validator`
+object. <angular/> passes in the input to validate as the first argument
+to your function. Any additional validator arguments are passed in as
+additional arguments to your function.
+
+You can use these variables in the function:
+
+* `this` — The current scope.
+* `this.$element` — The DOM element containing the binding. This allows the filter to manipulate
+ the DOM in addition to transforming the input.
+
+In this example we have written a upsTrackingNo validator.
+It marks the input text "valid" only when the user enters a well-formed
+UPS tracking number.
+
+@css ng-validation-error
+ When validation fails, this css class is applied to the binding, making its borders red by
+ default.
+
+@example
+<doc:example>
+ <doc:source>
+ <script>
+ angular.validator('upsTrackingNo', function(input, format) {
+ var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$");
+ return input.match(regexp)?"":"The format must match " + format;
+ });
+ </script>
+ <input type="text" name="trackNo" size="40"
+ ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'"
+ value="1Z 123 456 78 9012 345 6"/>
+ </doc:source>
+ <doc:scenario>
+ it('should validate correct UPS tracking number', function() {
+ expect(element('input[name=trackNo]').attr('class')).
+ not().toMatch(/ng-validation-error/);
+ });
+
+ it('should not validate in correct UPS tracking number', function() {
+ input('trackNo').enter('foo');
+ expect(element('input[name=trackNo]').attr('class')).
+ toMatch(/ng-validation-error/);
+ });
+ </doc:scenario>
+</doc:example>
diff --git a/docs/content/api/angular.widget.ngdoc b/docs/content/api/angular.widget.ngdoc
new file mode 100644
index 00000000..5fd7b259
--- /dev/null
+++ b/docs/content/api/angular.widget.ngdoc
@@ -0,0 +1,78 @@
+@workInProgress
+@ngdoc overview
+@name angular.widget
+@namespace Namespace for all widgets.
+@description
+# Overview
+Widgets allow you to create DOM elements that the browser doesn't
+already understand. You create the widget in your namespace and
+assign it behavior. You can only bind one widget per DOM element
+(unlike directives, in which you can use any number per DOM
+element). Widgets are expected to manipulate the DOM tree by
+adding new elements whereas directives are expected to only modify
+element properties.
+
+Widgets come in two flavors: element and attribute.
+
+# Element Widget
+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>
+&lt;my:watch exp="name"/&gt;
+</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>
+
+# Attribute Widget
+Let's implement the same widget, but this time as an attribute
+that can be added to any existing DOM element.
+<pre>
+&lt;div my:watch="name"&gt;text&lt;/div&gt;
+</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>
+
+@example
+<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>