| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  | extends ../../../ts/_cache/guide/dependency-injection.jade | 
					
						
							| 
									
										
										
										
											2016-01-21 09:49:13 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block includes | 
					
						
							|  |  |  |   include ../_util-fns | 
					
						
							|  |  |  |   - var _thisDot = ''; | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block ctor-syntax | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       We also leveraged Dart's constructor syntax for declaring parameters and | 
					
						
							|  |  |  |       initializing properties simultaneously. | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block injectable-not-always-needed-in-ts | 
					
						
							|  |  |  |   //- The [Angular 2 Dart Transformer](https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer) | 
					
						
							|  |  |  |   //- generates static code to replace the use of dart:mirrors. It requires that types be | 
					
						
							|  |  |  |   //- identified as targets for static code generation. Generally this is achieved | 
					
						
							|  |  |  |   //- by marking the class as @Injectable (though there are other mechanisms). | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block always-include-paren | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  |     Always write `@Injectable()`, not just `@Injectable`. | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  |     A metadata annotation must be either a reference to a | 
					
						
							|  |  |  |     compile-time constant variable or a call to a constant | 
					
						
							|  |  |  |     constructor such as `Injectable()`. | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  |     If we forget the parentheses, the analyzer will complain: | 
					
						
							|  |  |  |     "Annotation creation must have arguments". If we try to run the | 
					
						
							|  |  |  |     app anyway, it won't work, and the console will say | 
					
						
							|  |  |  |     "expression must be a compile-time constant". | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block real-logger | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       A real implementation would probably use the | 
					
						
							|  |  |  |       [logging package](https://pub.dartlang.org/packages/logging). | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 14:46:06 -07:00
										 |  |  | block provider-shorthand | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     This is actually a shorthand expression for a provider registration | 
					
						
							|  |  |  |     that creates a new instance of the | 
					
						
							|  |  |  |     [Provider](../api/angular2.core/Provider-class.html) class: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | block provider-ctor-args | 
					
						
							|  |  |  |   - var _secondParam = 'named parameter, such as <code>useClass</code>'  | 
					
						
							| 
									
										
										
										
											2016-03-03 22:50:42 -08:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  |     We supply two arguments (or more) to the `Provider` constructor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block dart-diff-const-metadata | 
					
						
							|  |  |  |   .callout.is-helpful | 
					
						
							|  |  |  |     header Dart difference: Constants in metadata | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       In Dart, the value of a metadata annotation must be a compile-time constant. | 
					
						
							|  |  |  |       For that reason, we can't call functions to get values | 
					
						
							|  |  |  |       to use within an annotation. | 
					
						
							|  |  |  |       Instead, we use constant literals or constant constructors. | 
					
						
							| 
									
										
										
										
											2016-06-03 18:00:53 +02:00
										 |  |  |       For example, a TypeScript program will use the | 
					
						
							|  |  |  |       object literal `{ provide: Logger, useClass: BetterLogger }`. | 
					
						
							| 
									
										
										
										
											2016-06-08 09:25:48 -07:00
										 |  |  |       A Dart annotation would instead use the constant value  | 
					
						
							|  |  |  |       `const Provider(Logger, useClass: BetterLogger)`. | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | block dart-diff-const-metadata-ctor | 
					
						
							|  |  |  |   .callout.is-helpful | 
					
						
							|  |  |  |     header Dart difference: Constants in metadata | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       Because Dart annotations must be compile-time constants, | 
					
						
							|  |  |  |       `useValue` is often used with string or list literals. | 
					
						
							|  |  |  |       However, `useValue` works with any constant object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       To create a class that can provide constant objects, | 
					
						
							|  |  |  |       ensure all its instance variables are `final`, | 
					
						
							|  |  |  |       and give it a `const` constructor. | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       Create a constant instance of the class by using `const` instead of `new`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // - var stylePattern = { otl: /(useValue.*\))/gm }; | 
					
						
							|  |  |  | // +makeExample('dependency-injection/dart/lib/providers_component.dart','providers-9','', stylePattern)(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block non-class-dep-eg | 
					
						
							|  |  |  |   span string, list, map, or maybe a function. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block config-obj-maps | 
					
						
							|  |  |  |   | . They can be  | 
					
						
							|  |  |  |   | <b><a href="https://api.dartlang.org/stable/dart-core/Map-class.html">Map</a></b> | 
					
						
							|  |  |  |   | literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block what-should-we-use-as-token | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     But what should we use as the token?  | 
					
						
							|  |  |  |     While we _could_ use **[Map][]**, we _should not_ because (like | 
					
						
							|  |  |  |     `String`) `Map` is too general. Our app might depend on several maps, each | 
					
						
							|  |  |  |     for a different purpose. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [Map]: https://api.dartlang.org/stable/dart-core/Map-class.html | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   .callout.is-helpful | 
					
						
							|  |  |  |     header Dart difference: Interfaces are valid tokens | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       In TypeScript, interfaces don't work as provider tokens. | 
					
						
							|  |  |  |       Dart doesn't have this limitation; | 
					
						
							|  |  |  |       every class implicitly defines an interface, | 
					
						
							|  |  |  |       so interface names are just class names. | 
					
						
							|  |  |  |       `Map` is a *valid* token even though it's the name of an abstract class; | 
					
						
							|  |  |  |       it's just *unsuitable* as a token because it's too general. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block dart-map-alternative | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     As an alternative to using a configuration `Map`, we can define | 
					
						
							|  |  |  |     a custom configuration class: | 
					
						
							| 
									
										
										
										
											2016-02-06 17:02:44 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 09:21:11 -07:00
										 |  |  |   +makeExcerpt('lib/app_config.dart (alternative config)','config-alt') | 
					
						
							| 
									
										
										
										
											2016-02-06 17:02:44 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:16:46 -07:00
										 |  |  |   :marked | 
					
						
							|  |  |  |     Defining a configuration class has a few benefits. One key benefit | 
					
						
							|  |  |  |     is strong static checking: we'll be warned early if we misspell a property | 
					
						
							|  |  |  |     name or assign it a value of the wrong type. | 
					
						
							|  |  |  |     The Dart [cascade notation][cascade] (`..`) provides a convenient means of initializing | 
					
						
							|  |  |  |     a configuration object.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If we use cascades, the configuration object can't be declared `const` and | 
					
						
							|  |  |  |     we can't use a [value provider](#value-provider).  | 
					
						
							|  |  |  |     A solution is to use a [factory provider](#factory-provider). | 
					
						
							|  |  |  |     We illustrate this next. We also show how to provide and inject the | 
					
						
							|  |  |  |     configuration object in our top-level `AppComponent`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [cascade]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#cascade | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   +makeExcerpt('lib/app_component.dart','providers') | 
					
						
							|  |  |  |   +makeExcerpt('lib/app_component.dart','ctor') |