Angular Dependency Injection in Depth - Resolution modifiers (2021)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello guys! My name is Dmytro Mezhenskyi. The agenda of today's video is resolution modifiers in angular dependency injection. I'm pretty sure that you have already seen such annotations like @Host(), @Self(), @SkipSelf() and @Optional(). In this video we will learn why do we need them, however in order to understand this topic you have to have some background. In previous video we have learned exactly how dependency injection works in Angular and how it resolves dependencies. If you didn't see this video yet I will just summarize the information from there So there are two injector hierarchies in Angular: Element injector and Modul injector hierarchy. And when we define and dependency in our component, first of all angular starts traversing the element injector tree and if nothing is found it delegates resolving of this service to model injector tree. if model injector tree also doesn't have this dependency you are getting the error. this is pretty much it what you have to know for this particular tutorial but if you need more detailed information you can check out my previous video right after this one. (but not now please). The link to that previous video you can find in the video description and there you will find also time codes which allow you easily navigate through the video. Subscribe to my channel right now and let's move on! Okay, what is resolution modifiers resolution modifiers it's some special annotations which allow you to slightly change the logic of how angular resolves dependency in the injectors tree as I mentioned before there are four resolution modifiers in angular: and this is @Optional(), @Self() @SkipSelf() and @Host() and we will cover today all of them. and let's start with the easiest one called @Optional(). So let's get back to our slides we see that when angular cannot resolve some dependency it throws an error and as you already may guess this @Optional() prevents this behaviour and if you decorate your dependency with this resolution modifier instead of error you will get just null so let's see it in action in real application i have created a completely new angular application for this lesson and now let's use our ngcli in order to create a new service so i just run ng generate service logger and i will add skip tests in order to skip tests and and CLI has generated a new service for me and injected it immediately in root modul injector. But i want to break my application and i'm going to remove provided in property in order to get an error from null injector then i have to inject my service right so i will do it in my app component ts file like this and now if i go to my browser and check a console i will see an error from my null injector and it's and it says that my logger service was not resolved which makes sense because we didn't provide it right now let's try to decorate it with optional annotation just be sure that you import it from right place okay and now if we go back to the browser we see that our application continued to work which means that optional decorator does its job so now you can go to the app component and do something like this so if service exists call method lock and it will log message otherwise just do nothing and let's create such a method for our service it just takes a message which is a string and it just logs it so that was an optional annotation as you can see it is really straightforward. The only one thing it does it just prevents our application from crashing if dependency was not found and let's move forward and have a look at the @Self() modifier. Well, before to start let's remove our optional annotation and then go to our service and provide it in our root model injector for this we just revert our provided in root property now if we reload our browser window we see that our logger is working fine and application works as expected okay now let's get back to our app component ts and try to decorate our dependency with @Self() annotation again make sure that it was imported from the right package now let's go to the browser and not injector says that not found but why why it doesn't work so we provided our service and we made sure that everything was working right before we add the self annotation well the thing is that self tries to resolve dependency only only in its own injector and it will not be asking the parent and go up through the injector three until it finds the ... until it finds provider It checks only its own injector and if it cannot resolve it there it will throw the error and in order to fix it we have to provide our logger service in component which declares this dependency in our case it is app component and we provide it by using providers property and add it here in providers array now you can see that error is gone and there are a couple of things uh worth to mention here the first one is that self applicable not only for node injectors but for any injector and you can even inject in in your module, right? so i can go to app model ts and inject in model constructor and it will work fine because all eagerly imported modules share their root module injector and our@Self() annotation will point out to exactly root injector and the second thing you have to know is that this instance in module is not the same instance as in app component once we provided it in our component decorator angular will create a separate instance and i can easily prove it by introducing a new public property in our service so let's call it prefix and by default it will be root and then i just slightly modify the lock method and i attach this prefix to our message now let's go to our app component and change our prefix to app component now if we reload we will see that we have two console logs in the first one we see prefix root and in the second app component which proves that this is two independent instances otherwise we would see the same prefix in both messages okay that was @Self() resolution modifier and i hope that everything is uh clear here and let's move on and talk a little bit about skip self well the skip self is very simple and does just opposite thing it just keeps injector where it was declared and results dependencies starting from its parent and it is easy to demonstrate if i just inject the same service but this time it will be decorated with skip self and in this case angulardi will skip this current node injector and will resolve one from the root module injector because there will be nothing to resolve in node injector tree and it will be delegated to module injector one and i can easily confirm it by calling the lock method of our second logger instance and in the method we will be able to see the prefix and if our theory is right we should see prefix root so let's go to the browser and here we go and we see in the console that we have prefix root so yeah that's it about skip self as you can see it really straightforward and just use it in case if you need to skip the current injector and start to resolve dependencies from apparent and above and now let's move forward and let's talk a little bit about @Host() resolution modifier well, @Host() resolution modifier tells angular that the host element should be the last stop when it is searching for providers but what does it mean well in order to better demonstrate this behavior let's create two directives parent directive and child directive so i will use angular cli in order to generate directive parent and then i will do the same for directive called child here we go and now let's build a hierarchy of node injectors so in app component template i will create a div where i apply parent directive and there inside a child div which has also child directive applied now let's declare dependency in our child directive and so far without any decorator and let's log the message in order to see the prefix of result service. If i reload the page we'll see that the prefix is app component and it is makes sense because angular will check injector of child directive which is empty then the same will be for parent directive and then it will end up in app component injector which has a provider for this service now let's try to provide the slogger for parent directive so i add a provider and in order to distinguish that this is an instance from exactly this directive i will inject this in our constructor by using self resolution modifier and also i will do it optional so if i remove the provider it will not break my app and then in constructor i will check if my instance exists i will change the prefix to the parent directive and now if we reload the page we see that prefix parent directive was printed everything makes sense so far right angular checks provider in child directive then it goes up to the parent directive parent directive has such a provider so we get this instance in child directive and now let's try to decorate dependency in our child directive with a host all right i save it go back and nothing has been changed it works the same as before what if we remove provider from parent directive all right i remove it and let's go back and now we see the error not found interesting right so it turns out that the host restricts the resolution of service in scope of components view, so it it even doesn't go to the component injector in order to reach our providers here because it is already out of the host scope so in our case parent directive was the latest place where this dependency could be provided and resolved otherwise it fails that's how the host resolution modifier is working and i remember at some point I had to invest some significant amount of time in order to figure out how this resolution modifier works but i hope now i could make it clearer for you okay that was it for today hope you enjoyed this video and it helped you to figure out how these resolution modifiers are working in angular if you like this video please hit thumbs up and subscribe to my channel right now! And of course leave your feedback in comment section and write me where would you use this angular feature it would be really interesting. Thank you for attention, I wish you productive week, take care and see you in the future!
Info
Channel: Decoded Frontend
Views: 13,855
Rating: undefined out of 5
Keywords: angular dependency injection in depth, angular self vs host, angular dependency injection tutorial, angular 10 dependency injection explained, angular 10 dependency injection, dependency injection in angular 10, webdevelopment, angular 10 crash course, angular services and dependency injection, Angular 10 tutorial, dependency injection angular
Id: uVGnsmm9g-I
Channel Id: undefined
Length: 14min 39sec (879 seconds)
Published: Sun Oct 04 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.