From 924ffafc51cf53ddf97f13ad748bbbf6d80caf13 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Wed, 18 May 2011 12:17:16 -0700 Subject: fixing broken links --- docs/content/guide/compiler.ngdoc | 163 +++++++++++++++++ docs/content/guide/css.ngdoc | 46 +++++ docs/content/guide/di.ngdoc | 304 ++++++++++++++++++++++++++++++++ docs/content/guide/guide.compiler.ngdoc | 163 ----------------- docs/content/guide/guide.css.ngdoc | 46 ----- docs/content/guide/guide.di.ngdoc | 304 -------------------------------- docs/content/guide/index.ngdoc | 5 +- docs/content/guide/overview.ngdoc | 2 +- 8 files changed, 515 insertions(+), 518 deletions(-) create mode 100644 docs/content/guide/compiler.ngdoc create mode 100644 docs/content/guide/css.ngdoc create mode 100644 docs/content/guide/di.ngdoc delete mode 100644 docs/content/guide/guide.compiler.ngdoc delete mode 100644 docs/content/guide/guide.css.ngdoc delete mode 100644 docs/content/guide/guide.di.ngdoc (limited to 'docs/content/guide') diff --git a/docs/content/guide/compiler.ngdoc b/docs/content/guide/compiler.ngdoc new file mode 100644 index 00000000..8896db43 --- /dev/null +++ b/docs/content/guide/compiler.ngdoc @@ -0,0 +1,163 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Compiler +@description + +#Compiler + +While angular might look like just a cool way to build web applications, the core of angular is +actually an HTML compiler. The default HTML transformations that this compiler provides are useful +for building generic apps, but you can also use them to create a domain-specific language for +building specific types of web applications. + +The compiler allows you to add behavior to existing HTML through widgets, directives, and text +markup. + +All of this compilation happens in the web browser, meaning no server is involved. + +# The compilation process +This section describes the steps that angular's HTML compiler goes through. If you use +`ng:autobind` in your application, this compilation process happens automatically when the +application is initialized (e.g. when the user loads the app in a browser). If you're an advanced +user using manual bind mode, you can decide when and how often the compilation happens. + +First, a bit of background of what the compilation step is for. Every type of +{@link angular.widget widget}, {@link angular.markup markup}, and +{@link angular.directive directive} in angular is defined with a compile function, and that +compile function returns an optional link function. Here is the relationship between the two: + + * **compile function** - registers a listener for the widget, markup, or directive's expression. + This function is called exactly once. + * **link function** - sets up the listener. This function can be called multiple times, once per + cloned DOM element (e.g. repeating element). + +Note that angular's built-in widgets, markup, and directives have predefined compile and link +functions that you don't need to modify. However, if you're writing your own widgets, markup, or +directives, you write compile and link functions. Refer to the Compiler API for more information. + +When the HTML compiler compiles a page, it goes through 3 phases: Compile, Create Root Scope, and +Link. + +## 1. Compile Phase + + * Recursively traverse the DOM, depth-first. + * Look for a matching compile function of type widget, then markup, then directive. + * If a compile function is found then execute it. + * When the compile function completes, it should return a link function. Aggregate this link + function with all link functions returned previously by step 1c. + * Repeat steps 1c and 1d for all compile functions found. The result of the compilation step is + the aggregate link function, which comprises all of the individual link functions. + +## 2. Create Root Scope + + * Inject all of the services into the root scope. + +## 3. Link Phase + + * Execute the aggregate link function with the root scope. The aggregate link function calls all + the individual link functions that were generated in the compile phase. + * 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: once for each iteration in a repeater. + +# Example + +The compilation process is best understood through example. Let's say that in your namespace my, +you want to create a new DOM element , which should display a greeting. + +If we want this HTML source: + +
+
+ +
+
+ +To produce this DOM: + +
+
+ + Hello + World! + +
+
+ +Write this widget definition (assuming you've already declared the my namespace in the page): + + +
+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('');
+    linkElement.append(salutationSpan);
+    linkElement.append(compiler.text(' '));
+    linkElement.append(nameSpan);
+    linkElement.append(compiler.text('!'));
+    this.$watch(salutationExp, function(value){
+      salutationSpan.text(value);
+    });
+    this.$watch(nameExp, function(value){
+    nameSpan.text(value);
+    });
+  };
+});
+
+ +Note: For more about widgets, see {@link angular.widget Widget}. + +## Compilation process for this example + +Here are the steps that the compiler goes through for the page that contains this widget definition: + +### Compile Phase + + * Recursively traverse the DOM depth-first. + * Find the angular.widget definition. + * Find and execute the widget's compileElement function, which includes the following steps: + * 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)). + * Extract the salutation and name HTML attributes as angular expressions. + * Return the aggregate link function, which includes just one link function in this example. + +### Link Phase + + * Execute the aggregate link function, which includes the following steps: + * Create a element set to the salutation class + * Create a element set to the name class. + * Add the span elements to the linkElement. (Note: be careful not to add them to the + compileElement, because that's the template.) + * Set up watches on the expressions. When an expression changes, copy the data to the + corresponding spans. + + +## Compiler API + +If you define your own widgets, markup, or directives, you need to access the compiler API. +This section describes the methods on the compiler that you can call. + +Note: As of 12 August 2010, these methods are subject to change. + +Recall that the compile function's this is a reference to the compiler. + + * `compile(element)` - returns `linker` - Invoke new instance of compiler to compile a DOM element + and return a linker function. You can apply the linker function to the original element or a + clone of the original element. The linker function returns a scope. + * `comment(commentText)` - returns `element` - Create a comment element. + * `element(elementName)` - returns `element` - Create an element by name. + * `text(text)` - returns `element` - Create a text element. + * `descend([set])` - returns `descend` - State Get or set the current descend state. If true the + compiler will descend to children elements. + * `directives([set])` - returns `directive` - State Get or set the current directives processing + state. The compiler will process directives only when directives set to true. + diff --git a/docs/content/guide/css.ngdoc b/docs/content/guide/css.ngdoc new file mode 100644 index 00000000..435186c9 --- /dev/null +++ b/docs/content/guide/css.ngdoc @@ -0,0 +1,46 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: CSS +@description + +# CSS +angular includes built-in CSS classes, which in turn have predefined CSS styles. + +# Built-in CSS classes + +## `ng-exception` + +**Usage:** angular applies this class to a DOM element if that element contains an Expression that +threw an exception when evaluated. + +**Styling:** The built-in styling of the ng-exception class displays an error message surrounded +by a solid red border, for example: + + >
Error message
+ + + +You can try to evaluate malformed expressions in {@link guide.expression expression} to see the +`ng-exception` class' styling. + +## `ng-validation-error` + +**Usage:** angular applies this class to an input widget element if that element's input does not +pass validation. Note that you set the validation criteria on the input widget element using the +Ng:validate or Ng:required directives. + +**Styling:** The built-in styling of the ng-validation-error class turns the border of the input +box red and includes a hovering UI element that includes more details of the validation error. You +can see an example in {@link angular.widget.@ng:validate ng:validate example}. + +## How to override the styles for built-in classes + +To override the styles for these built-in classes, you can do any of the following: + +Download the source code, edit angular.css, and host the source on your own server. +Create a local css file, overriding any styles that you'd like, and link to it from your HTML file +as you normally would: + +
+
+
diff --git a/docs/content/guide/di.ngdoc b/docs/content/guide/di.ngdoc new file mode 100644 index 00000000..6d9a746f --- /dev/null +++ b/docs/content/guide/di.ngdoc @@ -0,0 +1,304 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Dependency Injection +@description +Dependency injection (DI) is one of the core design patterns in angular and angular applications. DI +allows you to replace almost any part of angular framework or angular application with a custom +implementation, allowing for a highly flexible, maintainable and testable code-base. + +Dependency injection is a very common pattern in Java and other statically typed languages. While +undervalued among JavaScript developers, we feel strongly that DI in JavaScript allows us to achieve +the same benefits as in other languages. + +This document will focus on using dependency injection in angular. It is outside of the scope of +this document to explain details of dependency injection. For more information on this topic, please +refer to these links: + + * {@link http://en.wikipedia.org/wiki/Dependency_injection DI - Wikipedia} + * {@link http://martinfowler.com/articles/injection.html Inversion of Control by Martin Fowler} + * Java + * {@link http://code.google.com/p/google-guice/ Guice} + * {@link http://www.devshed.com/c/a/Java/The-Spring-Framework-Understanding-IoC/ Spring} + * {@link http://picocontainer.org/injection.html picoContainer} + * .NET + * {@link http://msdn.microsoft.com/en-us/magazine/cc163739.aspx MSDN Design Patterns - Dependency Inject} + * {@link http://www.springframework.net/ Spring.NET} + + + +# Dependency Injection in angular + +Angular's dependency injection story begins with a `service`. Service in angular lingo is a +JavaScript object, function, or value that is created by angular's injector via a provided factory +function. The factory function is registered with angular via {@link angular.service}. + +
+// register a factory for a uniqueId service.
+angular.service('uniqueId', function(){
+  // calling the factory function creates the instance function
+  var id = 0;
+  return function(){
+   // calling the counter instance function will return and increment the count
+   return ++id;
+  }
+});
+
+ +At run-time we can access the `uniqueId` service by looking it up with the service locator like +this: + +
+// create new root scope which has the injector function `$service()`
+var scope = angular.scope();
+
+// use the `$service` function to look up the service instance function
+var idGenerator = scope.$service('uniqueId');
+expect(idGenerator()).toBe(1);
+
+// subsequent lookups using the same root scope return the service instance
+var idGenerator2 = scope.$service('uniqueId');
+expect(idGenerator).toBe(idGenerator2);
+
+// since it is same instance calling idGenerator2 returns 2;
+expect(idGenerator2()).toBe(2);
+
+ +The {@link angular.service service} registry seems like a lot of work, so what are the benefits? To +answer this question, it’s important to realize that in large scale applications there are a lot of +services which are often dependent on each other, as in this example: + +
+angular.service('gadgetFactory', function(uniqueId){
+  return function(){
+    return {gadgetId: uniqueId()};
+  };
+}, {$inject: ['uniqueId']});
+
+ +Specifically, notice that the `gadgetFactory` takes `uniqueId` service in its arguments. It also +declares this dependency with the `$inject` property. There are several benefits to this approach: + +* There is no need for a `main` method for an application responsible for instantiating and wiring +these services. The order of service instantiation and wiring can be inferred by examining the +`$inject` annotations. +* It is easy to replace any one service with a different implementation without having to track down +all of the dependencies. This is useful in: + * Tests: when mocks of services are needed (for example using mock {@link angular.service.$xhr}.) + * Customization: when the service bundled with angular does not do exactly what the application +requires. + +More importantly, as we'll soon learn, controllers and other components of angular applications can +also declare their dependencies on services and these will be provided without explicitly looking +them up, but let's not get ahead of ourselves. + +Lastly, it is important to realize that all angular services are singletons – application singletons +to be more precise. This means that there is only one instance of a given service per injector. And +since angular is lethally allergic to the global state, it's absolutely possible to create multiple +injectors each with its own instance of a given service (but that is not typically needed, except in +tests where this property is crucially important). + + +## Service Locator and Scope + +The {@link angular.injector injector} is responsible for resolving the service dependencies in the +application. It gets created and configured with the creation of a root scope in your application. +The injector is responsible for caching the instances of services, but this cache is bound to the +scope. This means that different root scopes will have different instances of the injector. While +typical angular applications will only have one root scope (and hence the services will act like +application singletons), in tests it is important to not share singletons across test invocations +for isolation reasons. We get this isolation by having each test create its own separate root scope. + +
+// crate a root scope
+var rootScope = angular.scope();
+// accesss the service locator
+var myService = rootScope.$service('myService');
+
+ + + +# Dependency Injection in Controllers + +So far we have been talking about injector as a service locator. This is because we have been +explicitly calling the `$service` method to gain access to the service. Service locator is not +dependency injection since the caller is still responsible for retrieving the dependencies. *True +dependency injection is like Chuck Norris. Chuck does not ask for dependencies; he declares them.* + +The most common place to use dependency injection in angular applications is in +{@link angular.directive.@ng:controller controllers}. Here’s a simple example: + +
+function MyController($route){
+  // configure the route service
+  $route.when(...);
+}
+MyController.$inject = ['$route'];
+
+ +In this example, the `MyController` constructor function takes one argument, the +{@link angular.service.$route $route} service. Angular is then responsible for supplying the +instance of `$route` to the controller when the constructor is instantiated. There are two ways to +cause controller instantiation – by configuring routes with the $route service or by referencing the +controller from the HTML template, such as: + +
+
+
+ 
+ 
+  ...
+ 
+
+
+ +When angular is instantiating your controller, it needs to know what services, if any, should be +injected (passed in as arguments) into the controller. Since there is no reflection in JavaScript, +we have to supply this information to angular in the form of an additional property on the +controller constructor function called `$inject`. Think of it as annotations for JavaScript. + +
+MyController.$inject = ['$route'];
+
+ +The information in `$inject` is then used by the {@link angular.injector injector} to call the +function with the correct arguments. + + + +# Using Dependency Injection pragmatically + +At times you’ll need to use dependency injection pragmatically, usually when instantiating +controllers manually or writing unit tests. This section explains how to go about it. + +## Retrieving Services + +The simplest form of dependency injection is manual retrieval of scopes, known as service locator. +We say manual because we are asking the injector for an instance of the service (rather then having +the injector provide them to the function). This should be rare since most of the time the dependent +services should be injected into the controller using the `$inject` property array. + +
+// create a root scope. The root scope will automatically have
+// `$service` method defined which is configured with all services.
+// Each instance of root scope will have separate instances of services.
+var rootScope = angular.scope();
+
+// ask for a service explicitly
+var $window = rootScope.$service('$window');
+
+ + +## Creating Controllers using Dependency Injection + +In a typical angular application the dependency injection is most commonly used when creating +controllers. +
+// declare our own service by registering a factory function.
+angular.service('counter', function(){
+  var count = 0;
+  return function(){ return count++; };
+});
+
+// example of a controller which depends on '$window' and 'counter' service
+// notice that there is an extra unbound parameter 'name' which will not
+// be injected and must be supplied by the caller.
+function MyController($window, counter, name) {
+}
+
+// we must declare the dependencies explicitly and in the same order as in
+// the constructor function. This information is used by the dependency
+// injection to supply the arguments.
+// Notice the lack of 'name' argument which makes it an unbound argument.
+MyController.$inject = ['$window', 'counter'];
+
+
+// Create a root scope which creates the the injector
+var rootScope = angular.scope();
+
+// use the '$new()' method instead of standard 'new' keyword operator to
+// create an instance of MyController and have the dependency injection
+// supply the arguments to the controller. The dependency injection only
+// supplies the bound arguments in `$inject` all addition arguments are
+// curried from the '$new', in our case 'Alexandria' is the argument which
+// will be curried to the 'name' argument, while '$window' and 'counter'
+// are supplied by the dependency injection.
+var myController = rootScope.$new(MyController, 'Alexandria');
+// NOTE: the returning controller will be a child scope of parent scope,
+// in this case the root scope.
+
+ + +## Calling functions and Curring of arguments + +NOTE: this section is quite lame. The concept it is trying to describe is more closely related to +scope#new than scope#$service. We need a better example to discuss here. Ideally a parent controller +creating a child controller imperatively via $new where the child controller's constructor function +declares a portion of its dependencies via $inject property, but another portion is supplied by the +caller of $new (e.g. parentCtrl.$new(ChildCtrl, configParam1, configParam2); + +Finally, you may need to call functions but have the `$inject` properties of the function be +supplied by the injector. + +
+// create a root scope with the `$service` injector.
+var rootScope = angular.scope();
+
+// given a function such as
+function greet ($window, name) {
+  $window.alert(this.salutation + ' ' + name);
+}
+greet.$inject = ['$window'];
+
+// you can call function 'greet' such that the injector supplies the
+// '$window' and the caller supplies the function 'this' and the 'name'
+// argument.
+var fnThis = {salutation: 'Hello'}
+rootScope.$service(greet, fnThis, 'world');
+
+ + + +# Inferring `$inject` + +**EXPERIMENTAL: this is an experimental feature, see the important note at the end of this section +for drawbacks.** + +We resort to `$inject` and our own annotation because there is no way in JavaScript to get a list of +arguments. Or is there? It turns out that calling `.toString()` on a function returns the function +declaration along with the argument names as shown below: + +
+function myFn(a,b){}
+expect(myFn.toString()).toEqual('function myFn(a,b){}');
+
+ +This means that angular can infer the function names after all and use that information to generate +the `$inject` annotation automatically. Therefore the following two function definitions are +equivalent: + +
+// given a user defined service
+angular.service('serviceA', ...);
+
+// inject '$window', 'serviceA', curry 'name';
+function fnA($window, serviceA, name){};
+fnA.$inject = ['$window', 'serviceA'];
+
+// inject '$window', 'serviceA', curry 'name';
+function fnB($window, serviceA_, name){};
+// implies: fnB.$inject = ['$window', 'serviceA'];
+
+ +If angular does not find an `$inject` annotation on the function, then it calls the `.toString()` +and tries to infer what should be injected using the following rules: + +* any argument starting with `$` is angular service and will be added to `$inject` property array. +* any argument ending with `_` will be added to the `$inject` property array but we strip the `_` +* all arguments following an argument which has neither `$` nor `_` , must not have `$` nor `_` + (these are free arguments for {@link http://en.wikipedia.org/wiki/Currying curring}) + +**IMPORTANT** +Minifiers/obfuscators change the names of function arguments and will therefore break the `$inject` +inference. For this reason, either explicitly declare the `$inject` or do not use +minifiers/obfuscators. In the future, we may provide a pre-processor which will scan the source code +and insert the `$inject` into the source code so that it can be minified/obfuscated. diff --git a/docs/content/guide/guide.compiler.ngdoc b/docs/content/guide/guide.compiler.ngdoc deleted file mode 100644 index 8896db43..00000000 --- a/docs/content/guide/guide.compiler.ngdoc +++ /dev/null @@ -1,163 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: Compiler -@description - -#Compiler - -While angular might look like just a cool way to build web applications, the core of angular is -actually an HTML compiler. The default HTML transformations that this compiler provides are useful -for building generic apps, but you can also use them to create a domain-specific language for -building specific types of web applications. - -The compiler allows you to add behavior to existing HTML through widgets, directives, and text -markup. - -All of this compilation happens in the web browser, meaning no server is involved. - -# The compilation process -This section describes the steps that angular's HTML compiler goes through. If you use -`ng:autobind` in your application, this compilation process happens automatically when the -application is initialized (e.g. when the user loads the app in a browser). If you're an advanced -user using manual bind mode, you can decide when and how often the compilation happens. - -First, a bit of background of what the compilation step is for. Every type of -{@link angular.widget widget}, {@link angular.markup markup}, and -{@link angular.directive directive} in angular is defined with a compile function, and that -compile function returns an optional link function. Here is the relationship between the two: - - * **compile function** - registers a listener for the widget, markup, or directive's expression. - This function is called exactly once. - * **link function** - sets up the listener. This function can be called multiple times, once per - cloned DOM element (e.g. repeating element). - -Note that angular's built-in widgets, markup, and directives have predefined compile and link -functions that you don't need to modify. However, if you're writing your own widgets, markup, or -directives, you write compile and link functions. Refer to the Compiler API for more information. - -When the HTML compiler compiles a page, it goes through 3 phases: Compile, Create Root Scope, and -Link. - -## 1. Compile Phase - - * Recursively traverse the DOM, depth-first. - * Look for a matching compile function of type widget, then markup, then directive. - * If a compile function is found then execute it. - * When the compile function completes, it should return a link function. Aggregate this link - function with all link functions returned previously by step 1c. - * Repeat steps 1c and 1d for all compile functions found. The result of the compilation step is - the aggregate link function, which comprises all of the individual link functions. - -## 2. Create Root Scope - - * Inject all of the services into the root scope. - -## 3. Link Phase - - * Execute the aggregate link function with the root scope. The aggregate link function calls all - the individual link functions that were generated in the compile phase. - * 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: once for each iteration in a repeater. - -# Example - -The compilation process is best understood through example. Let's say that in your namespace my, -you want to create a new DOM element , which should display a greeting. - -If we want this HTML source: - -
-
- -
-
- -To produce this DOM: - -
-
- - Hello - World! - -
-
- -Write this widget definition (assuming you've already declared the my namespace in the page): - - -
-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('');
-    linkElement.append(salutationSpan);
-    linkElement.append(compiler.text(' '));
-    linkElement.append(nameSpan);
-    linkElement.append(compiler.text('!'));
-    this.$watch(salutationExp, function(value){
-      salutationSpan.text(value);
-    });
-    this.$watch(nameExp, function(value){
-    nameSpan.text(value);
-    });
-  };
-});
-
- -Note: For more about widgets, see {@link angular.widget Widget}. - -## Compilation process for this example - -Here are the steps that the compiler goes through for the page that contains this widget definition: - -### Compile Phase - - * Recursively traverse the DOM depth-first. - * Find the angular.widget definition. - * Find and execute the widget's compileElement function, which includes the following steps: - * 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)). - * Extract the salutation and name HTML attributes as angular expressions. - * Return the aggregate link function, which includes just one link function in this example. - -### Link Phase - - * Execute the aggregate link function, which includes the following steps: - * Create a element set to the salutation class - * Create a element set to the name class. - * Add the span elements to the linkElement. (Note: be careful not to add them to the - compileElement, because that's the template.) - * Set up watches on the expressions. When an expression changes, copy the data to the - corresponding spans. - - -## Compiler API - -If you define your own widgets, markup, or directives, you need to access the compiler API. -This section describes the methods on the compiler that you can call. - -Note: As of 12 August 2010, these methods are subject to change. - -Recall that the compile function's this is a reference to the compiler. - - * `compile(element)` - returns `linker` - Invoke new instance of compiler to compile a DOM element - and return a linker function. You can apply the linker function to the original element or a - clone of the original element. The linker function returns a scope. - * `comment(commentText)` - returns `element` - Create a comment element. - * `element(elementName)` - returns `element` - Create an element by name. - * `text(text)` - returns `element` - Create a text element. - * `descend([set])` - returns `descend` - State Get or set the current descend state. If true the - compiler will descend to children elements. - * `directives([set])` - returns `directive` - State Get or set the current directives processing - state. The compiler will process directives only when directives set to true. - diff --git a/docs/content/guide/guide.css.ngdoc b/docs/content/guide/guide.css.ngdoc deleted file mode 100644 index 6e028f30..00000000 --- a/docs/content/guide/guide.css.ngdoc +++ /dev/null @@ -1,46 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: CSS -@description - -# CSS -angular includes built-in CSS classes, which in turn have predefined CSS styles. - -# Built-in CSS classes - -## `ng-exception` - -**Usage:** angular applies this class to a DOM element if that element contains an Expression that -threw an exception when evaluated. - -**Styling:** The built-in styling of the ng-exception class displays an error message surrounded -by a solid red border, for example: - - >
Error message
- - - -You can try to evaluate malformed expressions in {@link angualr.expression expression} to see the -`ng-exception` class' styling. - -## `ng-validation-error` - -**Usage:** angular applies this class to an input widget element if that element's input does not -pass validation. Note that you set the validation criteria on the input widget element using the -Ng:validate or Ng:required directives. - -**Styling:** The built-in styling of the ng-validation-error class turns the border of the input -box red and includes a hovering UI element that includes more details of the validation error. You -can see an example in {@link angular.widget.@ng:validate ng:validate example}. - -## How to override the styles for built-in classes - -To override the styles for these built-in classes, you can do any of the following: - -Download the source code, edit angular.css, and host the source on your own server. -Create a local css file, overriding any styles that you'd like, and link to it from your HTML file -as you normally would: - -
-
-
diff --git a/docs/content/guide/guide.di.ngdoc b/docs/content/guide/guide.di.ngdoc deleted file mode 100644 index 2d1f92eb..00000000 --- a/docs/content/guide/guide.di.ngdoc +++ /dev/null @@ -1,304 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: Dependency Injection -@description -Dependency injection (DI) is one of the core design patterns in angular and angular applications. DI -allows you to replace almost any part of angular framework or angular application with a custom -implementation, allowing for a highly flexible, maintainable and testable code-base. - -Dependency injection is a very common pattern in Java and other statically typed languages. While -undervalued among JavaScript developers, we feel strongly that DI in JavaScript allows us to achieve -the same benefits as in other languages. - -This document will focus on using dependency injection in angular. It is outside of the scope of -this document to explain details of dependency injection. For more information on this topic, please -refer to these links: - - * {@link http://en.wikipedia.org/wiki/Dependency_injection DI - Wikipedia} - * {@link http://martinfowler.com/articles/injection.html Inversion of Control by Martin Fowler} - * Java - * {@link http://code.google.com/p/google-guice/ Guice} - * {@link http://www.devshed.com/c/a/Java/The-Spring-Framework-Understanding-IoC/ Spring} - * {@link http://picocontainer.org/injection.html picoContainer} - * .NET - * {@link http://msdn.microsoft.com/en-us/magazine/cc163739.aspx MSDN Design Patterns - Dependency Inject} - * {@link http://www.springframework.net/ Spring.NET} - - - -# Dependency Injection in angular - -Angular's dependency injection story begins with a `service`. Service in angular lingo is a -JavaScript object, function, or value that is created by angular's injector via a provided factory -function. The factory function is registered with angular via {@link angular.service}. - -
-// register a factory for a uniqueId service.
-angular.service('uniqueId', function(){
-  // calling the factory function creates the instance function
-  var id = 0;
-  return function(){
-   // calling the counter instance function will return and increment the count
-   return ++id;
-  }
-});
-
- -At run-time we can access the `uniqueId` service by looking it up with the service locator like -this: - -
-// create new root scope which has the injector function `$service()`
-var scope = angular.scope();
-
-// use the `$service` function to look up the service instance function
-var idGenerator = scope.$service('uniqueId');
-expect(idGenerator()).toBe(1);
-
-// subsequent lookups using the same root scope return the service instance
-var idGenerator2 = scope.$service('uniqueId');
-expect(idGenerator).toBe(idGenerator2);
-
-// since it is same instance calling idGenerator2 returns 2;
-expect(idGenerator2()).toBe(2);
-
- -The {@link angular.service service} registry seems like a lot of work, so what are the benefits? To -answer this question, it’s important to realize that in large scale applications there are a lot of -services which are often dependent on each other, as in this example: - -
-angular.service('gadgetFactory', function(uniqueId){
-  return function(){
-    return {gadgetId: uniqueId()};
-  };
-}, {$inject: ['uniqueId']});
-
- -Specifically, notice that the `gadgetFactory` takes `uniqueId` service in its arguments. It also -declares this dependency with the `$inject` property. There are several benefits to this approach: - -* There is no need for a `main` method for an application responsible for instantiating and wiring -these services. The order of service instantiation and wiring can be inferred by examining the -`$inject` annotations. -* It is easy to replace any one service with a different implementation without having to track down -all of the dependencies. This is useful in: - * Tests: when mocks of services are needed (for example using mock {@link angular.service.$xhr}.) - * Customization: when the service bundled with angular does not do exactly what the application -requires. - -More importantly, as we'll soon learn, controllers and other components of angular applications can -also declare their dependencies on services and these will be provided without explicitly looking -them up, but let's not get ahead of ourselves. - -Lastly, it is important to realize that all angular services are singletons – application singletons -to be more precise. This means that there is only one instance of a given service per injector. And -since angular is lethally allergic to the global state, it's absolutely possible to create multiple -injectors each with its own instance of a given service (but that is not typically needed, except in -tests where this property is crucially important). - - -## Service Locator and Scope - -The {@link angular.injector injector} is responsible for resolving the service dependencies in the -application. It gets created and configured with the creation of a root scope in your application. -The injector is responsible for caching the instances of services, but this cache is bound to the -scope. This means that different root scopes will have different instances of the injector. While -typical angular applications will only have one root scope (and hence the services will act like -application singletons), in tests it is important to not share singletons across test invocations -for isolation reasons. We get this isolation by having each test create its own separate root scope. - -
-// crate a root scope
-var rootScope = angular.scope();
-// accesss the service locator
-var myService = rootScope.$service('myService');
-
- - - -# Dependency Injection in Controllers - -So far we have been talking about injector as a service locator. This is because we have been -explicitly calling the `$service` method to gain access to the service. Service locator is not -dependency injection since the caller is still responsible for retrieving the dependencies. *True -dependency injection is like Chuck Norris. Chuck does not ask for dependencies; he declares them.* - -The most common place to use dependency injection in angular applications is in -{@link angular.ng:controller controllers}. Here’s a simple example: - -
-function MyController($route){
-  // configure the route service
-  $route.when(...);
-}
-MyController.$inject = ['$route'];
-
- -In this example, the `MyController` constructor function takes one argument, the -{@link angular.service.$route $route} service. Angular is then responsible for supplying the -instance of `$route` to the controller when the constructor is instantiated. There are two ways to -cause controller instantiation – by configuring routes with the $route service or by referencing the -controller from the HTML template, such as: - -
-
-
- 
- 
-  ...
- 
-
-
- -When angular is instantiating your controller, it needs to know what services, if any, should be -injected (passed in as arguments) into the controller. Since there is no reflection in JavaScript, -we have to supply this information to angular in the form of an additional property on the -controller constructor function called `$inject`. Think of it as annotations for JavaScript. - -
-MyController.$inject = ['$route'];
-
- -The information in `$inject` is then used by the {@link angular.injector injector} to call the -function with the correct arguments. - - - -# Using Dependency Injection pragmatically - -At times you’ll need to use dependency injection pragmatically, usually when instantiating -controllers manually or writing unit tests. This section explains how to go about it. - -## Retrieving Services - -The simplest form of dependency injection is manual retrieval of scopes, known as service locator. -We say manual because we are asking the injector for an instance of the service (rather then having -the injector provide them to the function). This should be rare since most of the time the dependent -services should be injected into the controller using the `$inject` property array. - -
-// create a root scope. The root scope will automatically have
-// `$service` method defined which is configured with all services.
-// Each instance of root scope will have separate instances of services.
-var rootScope = angular.scope();
-
-// ask for a service explicitly
-var $window = rootScope.$service('$window');
-
- - -## Creating Controllers using Dependency Injection - -In a typical angular application the dependency injection is most commonly used when creating -controllers. -
-// declare our own service by registering a factory function.
-angular.service('counter', function(){
-  var count = 0;
-  return function(){ return count++; };
-});
-
-// example of a controller which depends on '$window' and 'counter' service
-// notice that there is an extra unbound parameter 'name' which will not
-// be injected and must be supplied by the caller.
-function MyController($window, counter, name) {
-}
-
-// we must declare the dependencies explicitly and in the same order as in
-// the constructor function. This information is used by the dependency
-// injection to supply the arguments.
-// Notice the lack of 'name' argument which makes it an unbound argument.
-MyController.$inject = ['$window', 'counter'];
-
-
-// Create a root scope which creates the the injector
-var rootScope = angular.scope();
-
-// use the '$new()' method instead of standard 'new' keyword operator to
-// create an instance of MyController and have the dependency injection
-// supply the arguments to the controller. The dependency injection only
-// supplies the bound arguments in `$inject` all addition arguments are
-// curried from the '$new', in our case 'Alexandria' is the argument which
-// will be curried to the 'name' argument, while '$window' and 'counter'
-// are supplied by the dependency injection.
-var myController = rootScope.$new(MyController, 'Alexandria');
-// NOTE: the returning controller will be a child scope of parent scope,
-// in this case the root scope.
-
- - -## Calling functions and Curring of arguments - -NOTE: this section is quite lame. The concept it is trying to describe is more closely related to -scope#new than scope#$service. We need a better example to discuss here. Ideally a parent controller -creating a child controller imperatively via $new where the child controller's constructor function -declares a portion of its dependencies via $inject property, but another portion is supplied by the -caller of $new (e.g. parentCtrl.$new(ChildCtrl, configParam1, configParam2); - -Finally, you may need to call functions but have the `$inject` properties of the function be -supplied by the injector. - -
-// create a root scope with the `$service` injector.
-var rootScope = angular.scope();
-
-// given a function such as
-function greet ($window, name) {
-  $window.alert(this.salutation + ' ' + name);
-}
-greet.$inject = ['$window'];
-
-// you can call function 'greet' such that the injector supplies the
-// '$window' and the caller supplies the function 'this' and the 'name'
-// argument.
-var fnThis = {salutation: 'Hello'}
-rootScope.$service(greet, fnThis, 'world');
-
- - - -# Inferring `$inject` - -**EXPERIMENTAL: this is an experimental feature, see the important note at the end of this section -for drawbacks.** - -We resort to `$inject` and our own annotation because there is no way in JavaScript to get a list of -arguments. Or is there? It turns out that calling `.toString()` on a function returns the function -declaration along with the argument names as shown below: - -
-function myFn(a,b){}
-expect(myFn.toString()).toEqual('function myFn(a,b){}');
-
- -This means that angular can infer the function names after all and use that information to generate -the `$inject` annotation automatically. Therefore the following two function definitions are -equivalent: - -
-// given a user defined service
-angular.service('serviceA', ...);
-
-// inject '$window', 'serviceA', curry 'name';
-function fnA($window, serviceA, name){};
-fnA.$inject = ['$window', 'serviceA'];
-
-// inject '$window', 'serviceA', curry 'name';
-function fnB($window, serviceA_, name){};
-// implies: fnB.$inject = ['$window', 'serviceA'];
-
- -If angular does not find an `$inject` annotation on the function, then it calls the `.toString()` -and tries to infer what should be injected using the following rules: - -* any argument starting with `$` is angular service and will be added to `$inject` property array. -* any argument ending with `_` will be added to the `$inject` property array but we strip the `_` -* all arguments following an argument which has neither `$` nor `_` , must not have `$` nor `_` - (these are free arguments for {@link http://en.wikipedia.org/wiki/Currying curring}) - -**IMPORTANT** -Minifiers/obfuscators change the names of function arguments and will therefore break the `$inject` -inference. For this reason, either explicitly declare the `$inject` or do not use -minifiers/obfuscators. In the future, we may provide a pre-processor which will scan the source code -and insert the `$inject` into the source code so that it can be minified/obfuscated. diff --git a/docs/content/guide/index.ngdoc b/docs/content/guide/index.ngdoc index 2798210d..1a9d2555 100644 --- a/docs/content/guide/index.ngdoc +++ b/docs/content/guide/index.ngdoc @@ -31,7 +31,4 @@ * {@link angular.service Service} - Objects that are wired through dependency injection and then injected into the root scope. * {@link guide.testing Testing} - * service:$browser(mock) -* {@link downloading Downloading} - How to download, compile, and host the angular - environment on your own server. -* {@link guide.contribute Contributing} - How to contribute to angular project. + * service:$browser(mock) \ No newline at end of file diff --git a/docs/content/guide/overview.ngdoc b/docs/content/guide/overview.ngdoc index 61c58435..8723e839 100644 --- a/docs/content/guide/overview.ngdoc +++ b/docs/content/guide/overview.ngdoc @@ -112,7 +112,7 @@ These input widgets look normal enough, but consider these points: of the input widgets (`qty` and `cost`) to variables of the same name. Think of those variables as the "Model" part of the Model-View-Controller design pattern. * Note the angular directives, {@link angular.widget.@ng:validate ng:validate} and {@link -ngular.widget.@ng:required ng:required}. You may have noticed that when you enter invalid data or +angular.widget.@ng:required ng:required}. You may have noticed that when you enter invalid data or leave the the input fields blank, the borders turn a plainly irritated red color, and the display value disappears. These `ng:` directives make it easier to implement field validators than coding them in JavaScript, no? Yes. -- cgit v1.2.3