Dependency Injection
Angular dependency injection docs https://angular.io/docs/ts/latest/guide/dependency-injection.html
An important application design pattern. Angular has its own dependency injection framework, and we really can't build an Angular application without it. It's used so widely that almost everyone just calls it DI.
Where do i get the code?
https://github.td.teradata.com/ux/covalent-training/commits/feature/dependency-injection
Dependency Injection Graph
Here is an example on how dependency injection works depending on the component hierarchy.
Setup
Stash away any items not needed for this lab
git stash
Checkout the repo
git checkout 2a4cc6e7cd135312b413ded1354aef80a2f3dee8
start the local angular-cli server:
git serve
you should see
** NG Live Development Server is running on http://localhost:4200. **
Lets get started!
We need to create the service we want to start injecting in our module/components. For this we will create a DIService
and we will add a counter on it to keep track of its instance.
Example: https://github.td.teradata.com/ux/covalent-training/commit/2a4cc6e7cd135312b413ded1354aef80a2f3dee8
Why @Injectable()?
@Injectable() marks a class as available to an injector for instantiation. Generally speaking, an injector will report an error when trying to instantiate a class that is not marked as@Injectable()
.
Using a service without registering it
When trying to inject a service without registering it, you will get the following error:
What this means is that you are trying to use a service that is not recognized by angular nor part of any module (even if the code is there).
Example: https://github.td.teradata.com/ux/covalent-training/commit/f73ed6c5d765a8af17caf6f65c312e16b1ad5882
Providing a service
A provider provides the concrete, runtime version of a dependency value. The injector relies on providers to create instances of the services that the injector injects into components and other services.
Example: https://github.td.teradata.com/ux/covalent-training/commit/2bfc525f32ffb684bf6a39065327a084bfa3494d
This will let angular now that within the Overview component context, there should be an instance of DIService
created.
Providing a service in multiple components
Now that we know that we need to register a service as provider to be able to inject it, it seems easy to just go into every component where we need it and add it.
Example: https://github.td.teradata.com/ux/covalent-training/commit/b4af2b1fab9b4b87a6de2f081e73c56132d85f31
This however, might not be what we want in some cases since a new instance will be created in each place we provide it.
LogsComponent dependency injection:
OverviewComponent dependency injection:
The graphs let us know that there will be a different DIService
instance provided in both components.
Share a provider
Depending where we register a service, that instance will be created from there onward. So if we want to create a singleton service (same instance shared across the whole app), we need to register it at the module level.
Example: https://github.td.teradata.com/ux/covalent-training/commit/1aa93e8c7aad36ef8960616426a5569106597d60
OverviewComponent dependency injection:
OverviewComponent dependency injection:
Now we can see that the DIService
provided comes from root, so its the same instance.
Alternate class provider
Sometimes there is a need to override how a service works depending on the context, or a way to provide a more concrete implementation of a service. This can be done by using the following piece of code:
providers: [{
provider: DIService, useClass: CustomDIService
}]
Example: https://github.td.teradata.com/ux/covalent-training/commit/68f908b907bd717ecbf3ed5d3ae29cd66e0accf6
This will inject a CustomDIService
, anywhere DIService
is used from there on in the component hierarchy.