There are several ways we can configure resolving injected dependencies in Angular. For instance we can:
1) Inject a (singleton) instance of a class (as we’ve seen)
2) Inject a value
Using a Class
Injecting a singleton instance of a class is probably the most common type of injection. When we put the class itself into the list of providers like this:
providers: [ UserService ]
This tells Angular that we want to provide a singleton instance of UserService whenever UserService is injected. Because this pattern is so common, the class by itself is actually shorthand notation
for the following, equivalent configuration:
providers: [ { provide: UserService, useClass: UserService } ]
The object configuration with provide takes two keys. provide is the token that we use to identify the injection and the second useClass is how and what to inject. We’re mapping the UserService class to the UserService token. In this case, the name of the class and the token match. This is the common case, but know that the token and the injected thing aren’t required to have the same name.
As we’ve seen above, in this case the injector will create a singleton behind the scenes and return the same instance every time we inject it . Of course, the first time it is injected, the singleton hasn’t been instantiated yet, so when creating the UserService instance for the first time, the DI system will trigger the class constructor method.
Using a Value
Another way we can use DI is to provide a value, much like we might use a global constant. For instance, we might configure an API Endpoint URL depending on the environment.
To do this, in our NgModule providers, we use the key useValue:
providers: [ { provide: 'API_URL', useValue: 'http://my.api.com/v1' } ]
Above, for the provide token we’re using a string of API_URL. If we use a string for the provide value, Angular can’t infer which dependency we’re resolving by the type. For instance we can’t write:
// doesn't work - anti-example export class AnalyticsDemoComponent { constructor(apiUrl: 'API_URL') { // <--- this isn't a type, just a string // if we put `string` that is ambiguous } }
So what can we do? In this case, we’ll use the @Inject() decorator like this:
import { Inject } from '@angular/core'; export class AnalyticsDemoComponent { constructor(@Inject('API_URL') apiUrl: string) { // works! do something w/ apiUrl } }
For any query regarding Providers in Angular, drop a comment below.