extends ../../../ts/_cache/guide/dependency-injection.jade

block includes
  include ../_util-fns
  - var _thisDot = '';

block ctor-syntax
  .l-sub-section
    :marked
      We also leveraged Dart's constructor syntax for declaring parameters and
      initializing properties simultaneously.

block register-provider-ngmodule
  :marked
    Before we do, let's see an example of provider registration during bootstrapping:

  +makeExcerpt('app/main.1.ts (discouraged)', 'bootstrap-discouraged', '')

  :marked
    The injector now knows about our `HeroService`.
    An instance of our `HeroService` will be available for injection across our entire application.

    Of course we can't help wondering about that comment telling us not to do it this way.
    It *will* work. It's just not a best practice.
    The bootstrap provider option is intended for configuring and overriding Angular's own
    preregistered services, such as its routing support.

    The preferred approach is to register application providers in application components.
    Because the `HeroService` is used within the *Heroes* feature area &mdash;
    and nowhere else &mdash; the ideal place to register it is in the top-level `HeroesComponent`.

block ngmodule-vs-component
  :marked
    Look at the `providers` part of the `@Component` annotation.
    An instance of the `HeroService` is now available for injection in this `HeroesComponent`
    and all of its child components.

    The `HeroesComponent` itself doesn't happen to need the `HeroService`.
    But its child `HeroListComponent` does, so we head there next.

block injectable-not-always-needed-in-ts
  //- The [Angular 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).

block always-include-paren
  :marked
    Always write `@Injectable()`, not just `@Injectable`.
    A metadata annotation must be either a reference to a
    compile-time constant variable or a call to a constant
    constructor such as `Injectable()`.
    
    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".

block real-logger
  .l-sub-section
    :marked
      A real implementation would probably use the
      [logging package](https://pub.dartlang.org/packages/logging).

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:

block provider-ctor-args
  - var _secondParam = 'named parameter, such as <code>useClass</code>' 
  :marked
    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.
      For example, a TypeScript program will use the
      object literal `{ provide: Logger, useClass: BetterLogger }`.
      A Dart annotation would instead use the constant value 
      `const Provider(Logger, useClass: BetterLogger)`.

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:

  +makeExcerpt('lib/app_config.dart (alternative config)','config-alt')

  :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')
