Angular DI Context

What is DI context?

In simpler terms, the Angular Dependency Injection (DI) context is like a location or space where you can insert, or "inject," a provider.

The simplest example is an injectable constructor.

Other DI contexts: Field

In the initializer for fields of injectable classes.

Other DI contexts: useFactory

In the factory function specified for useFactory of a Provider or an @Injectable.

Other DI contexts: Custom

When you want to run a given function in an injection context without being in one, you can do it with runInInjectionContext

What are the pros & cons?

The best way to see the benefits of all approaches is to solve the same problem with different methods.

 

Problem:
We have feeds/notifications in our system and to properly maintain them we need to separate them by modules (verification module will contain verification-feed and verification-notification submodules etc.).

Currently, we do not need providers in our feed/notification, but it's just a matter of time before we will need them. Refactoring code to support DI may be challenging in the future, so we need to support them from the start.

What are the pros & cons?

There are 3 possible solutions to the problem:

 - class-based architecture (similar to angular class-based guards)

 - passing injector as parameter

 - inject-based architecture (similar to angular functional guards)

 

Let's have a look at each of these solutions in the code and see all the pros and cons.

Class-based solution

Class-based solution

Pros:

 - No code duplication

 - Support async logic

 

Cons:

 - Boilerplate

NOTE: Angular deprecated their class-based providers (like guards and interceptorcs) logic in favor of inject-based.

Injector-based solution

Injector-based solution

Pros:

 - No boilerplate

 - Support async logic

 

Cons:

 - harder to maintain as an injector in method parameters, so changing this would require changing a lot of dependent code

Inject-based solution

Inject-based solution

Pros:

 - Concise

 - No boilerplate

 

Cons:

 - no support for async code (there is workaround)

NOTE: Angular deprecated their class-based providers (like guards and interceptorcs) logic in favor of inject-based.

Better forms classes DX

Better forms classes DX

With help of inject method we can get required providers inside our non-injectable form classes. This would help us to get rid of destruction methods inside forms and remove extra form variable inside components.

Conclusion

Even though I think that both class-based and inject-based approaches would have their use cases, but seems that the angular community chose to move in the direction of the functional programming, so we need to move along with them and use more inject-based logic.

More info

Code examples

Thanks for your attention