NgTemplateOutlet in Angular - Everything You Have to Know (2022)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this video will teach you how to utilize an  angular ngTemplateOutlet directive to   create reusable components with customizable  and extensible Views you will learn everything   you have to know about this directive because  I'm going to cover all its available features   like creating views from angular templates how to  provide template context data and how to control   the proper angular dependence injection flow in  the embedded views so if you watch this video   Until the End, you can be sure that you will be  able to solve 80% of use cases where you   need to implement customizable view for your  angular components if you have first time on   my channel my name is Dmytro Mezhenskyi and here  you can find a lot of advanced angular tutorials   and courses you can check them out later but  now let's get started and enjoy this video all right let's get started and let me very  quickly onboard you and demonstrate the current   application what kind of problems this application  has and how we are going to fix those problems   uh so as you can see I've got some angular  component that renders the weather forecast and   it also has couple of buttons that perform some  action so we can refresh data of this widget and   we can copy information to our clipboard in order  to you know paste it somewhere of course all this   data and actions those are mocked data I didn't  want to bring the real implementation because I   wanted to keep stuff simple um so yeah this is  how it looks like and there is our component   rendered right here and here you can see the  implementation of this component as you can see   pretty straightforward we have just some template  that renders some data this data comes from some   certain State this state is represented as a separate service that is provided on the   for the injector of the wizard  weather widget which means that   uh those Services they will be single tones in  scope of this component and all its children right   the same for widget actions uh widget actions  those are set of uh just mocked services that   supposed to perform some useful actions and uh  yeah this is how it looks like you can see pretty   straightforward widget state is also very very  simple and what is what else I am this inject   function for those who just started with angular  this is same as an injection via Constructor so   you could see probably the construction like  this one right and this is pretty much the   same as this notation right this is just a new  way to do that all right and now let's quickly   talk about problems and limitations the problem  has and actually the biggest problem here is the   component template because if you have a look  at it you can easily notice that that template   is completely hard coded and you cannot change  it you cannot customize it and it might be a big   problem if you decide to distribute this component  as a part of some component library or if you need   to reuse this component in in other part of your  application but you have to change somehow look   and feel of this component it is not possible  and it is a problem and I'm going to tell you in   advance that there are a couple of ways of how to  customize the view of angular components the first   way is to use NG template oh sorry NG content  directive it is also known as a Content projection   and another approach is to create embedded view  from angular templates and this is exactly the   approach I'm going to use in this video because  I find it a bit more flexible compared to content   projection but if you'd like to learn more about  content projection as well uh please let me know   about that in the comments under this video and  hit thumbs up if I uh get enough let's say 1   000 likes under this video I will recognize that  this topic might be interesting for you and I will   create a dedicated uh video about that but now  let's move forward let's move forward and let's   quickly talk about how do we create uh embedded  views in angular so in order to create embedded   view in angular we need to have basically  two things we have to have some container   it's kind of Encore where exactly in the view  needs to be rendered there embedded View and   then we have to have the template that needs to  be instantiated and eventually rendered right   right so the container can be actually any HTML  note yeah we could create some another div and   Market as a container using the template variable  yeah and if we want to create angular template   from some piece of HTML code then we have to use  the NG template and place the HTML that is going   to be the angular template right between those  two tags and what is interesting about NG template   is that it is lazy so if I save it right now you  can see that everything disappeared it is because   we have to explicitly create the view from this  template and only then it will be visible so how   we usually create the embedded view in order to do  that we have to get reference to those two things   to the container and to the NG template so let  maybe name it as a as a default widget header and   then we can easily get reference to them by using  the huge child decorator so I get reference first   to the container and here is very important thing  if I leave it as it is then I will get reference   to the native div element and this is not what I'm  going to achieve I want to read from here the view   container ref right and if I want to get reference  to it I have to specify the config object for the   view child and provide here the read property and  say what exactly I want to read from this node and   from here I'm going to read The View container ref  like that so here I have to create a property here   we go and it's going to be the instance of view  container ref obviously right and then I have to   do the similar thing for the default widget header  so let's create another view child get a reference   to the default widget header template here I  don't need to specify anything because I need   to gather a direct reference to the NG template  right so let's name it header template and it's   going to be the template reference reference to  the template right and let it be any for now we   will talk about this type later in this video but  it is not enough those two just references right   and because we get references using view child it  means that those guys they will be available only   when the component view is instantiated and we  have a dedicated lifecycle hook for that called   and G after view in it right and inside this  lifecycle hook uh those guys as I said will be   available so I can use my container right and call  the method create embedded View and this method   expects that template that needs to be rendered  and I already have such a reference and it is   a header template property so like that and if I  save it right now you can see that the header view   is back and let's have a look how it looks in the  HTML so here is the our widget header and this is   the container right this is exactly this div and  next to the container there were they were Android   widget title and widget subtitle and those guys  they are coming from the angular template that   we created before I know you might be slightly  confused because you probably expected that the   template will be rendered inside the container  right but no it will be rendered next to them   container node and if you want to get read from  this HTML tag you can always use such a thing   called NG container and in this case you can see  that that empty div has disappeared because any   container it is being rendered eventually into  nothing yeah it works just like a placeholder   for some HTML notes but let's quickly get back  to our current implementation and the way we   implemented this feature right now it is so  called declarative Paradigm in programming   because we explicitly specify steps that needs to  be performed in order to get some desired result   yeah so we say that okay get a reference to The  Container get the reference to the header template   then inside NG after view you need lifecycle hook  create the embedded view blah blah blah blah blah   so we describe how things needs to be done from  Another Side there exists declarative parting   that describes what needs to be done for instance  I need to have embed that you created so here is   the template please create it I don't care how it  will be done I just need the final result so this   is the declarity of uh Paradigm in programming and  usually declarative programming is more readable   and easier to understand and in order to implement  this current feature we have right now but using   a declarative way we have to use NG template  Outlet directive that allows us to do that so   finally we started to talk about this directive  because I don't want just to show the feature I   want to teach you why this feature exists and  which problems does it solve so how it would   look like when we apply the NG template Outlet  directly so I can completely remove this stuff   then we obviously have to import this directive  yes so let's do that so I type NG template Outlet   or you could inject also a common model it is part  of the common model but yeah as you want and once   we have this directive imported we can apply  it to our NG container just like that and as a   value for it we have to provide a reference to the  template that needs to be eventually rendered so   like that and as you can see it works the same  way but it is more readable and less code needed   in order to achieve the same goal and I can also  remove all those stuff as well nice and there is   no any magic here actually under the hood if we  have a look at the source code of this directive   you can see that it does pretty much the same  yeah it has more like conditions whatever but   eventually it has also view container ref  and it creates embedded View and provides   the template that needs to be rendered and then  context injector like those stuff we will cover   late in this video but in a nutshell it is pretty  much the same what we have implemented just couple   of minutes ago all right now what benefits we can  get from refactoring our code to using a template   Outlet Plus uh angular template it means that here  we can dynamically provide any template we want we   can allow user to provide alternative templates we  can do it by using just regular inputs so I create   some separate input I name it like header template  I say that it needs to be the template ref again   so far it is any type and having that I can just  do something like that I can say that okay render   the template that user provided via component  input or if it's not provided then use default   widget header as a fallback and that's it so I  can save it you can see that nothing has changed   but now I can go to app component and create some  new NG template and I can say here that this is   some alternative widget header and there inside I  can play some alternative template right so I can   create something like that and here play something  like today's weather yeah and then the reference   to this template I can easily provide via this new  header template input just like that and if I save   it right now you can see that the header got the  new template that was provided from outside so   we replaced the default header with the new one  and if I remove this input from here it will fall   back to the default one right so this is the first  cool thing that you can Implement using ng10 blade   Outlet directive and yeah another thing I forgot  to say about the style so most probably you want   to apply some styles for this new alternative  template you can Define Styles in the component   where this template is declared so I declare  it inside app components so somewhere here I   can place the styles for my alternative header  right and if I save it those styles were applied   so let me close this and let's move forward to the  next feature so imagine that we have to we want   to implement the same thing but for our widget  content so let's get started to do that so I would   need to duplicate this input right and just maybe  rename it so I say that this is content template   and then I have to create a similar construction  for a video template as well so I create NG   container where I also apply the NG template  Outlet directive right and there I have to   create also the templates so let's create another  NG template like that and I say that this is the   default widget content like that and this engine  template should wrap this HTML so here we go   uh what I forgot I forgot to provide actually  values to the ntng template Outlet directive so   I say that it needs to take other content template  provided from user or it should have a fullback   that points to this engine template so here we go  then in order to provide the alternative content   view for this widget you probably uh go to the  app component you are going to create a new NG   template you are very excited that finally  we'll customize this component you start to   bring some new alternative view but then you are  quickly realize that okay you need to render the   temperature but where we will take this data  so here it is pretty much Clear yeah we get it   from the state uh this is the property of this  component but here we don't actually have the X   s to this data one of your suggestions could be  like okay we could get actually the reference   to the weather widget component instance using  uh view child decorator right and once we get   the reference we could simply read the state  property from the component and then render the   value we need inside the alternative template  the solution would theoretically work and in   practice it would also work but this solution  is quite terrible because imagine that you have   not only one weather widget here but you have I  know dozens of them then you would need to get   reference to all of them track if you properly  resolve States for each of this weather widget   instances also you might have them implementation  of the component where the state is protected or   private then even even if you get a reference  to it you will not be able to read this property   because it is just protected yeah so this solution  isn't the best one and let me show you another one   that works perfectly for that and this is where  NG template Outlet context property comes into   the play and template context it is nothing  else as Chester data that is available for   some particular angular template and in order  to provide this data to that template we have   to use a special property of the NG template  Outlet directive and it is simply called NG   template Outlet context and as I said it is just  the data which can be represented as object and   we can say that for this template that can be  available a variable like temperature and their   value for the temperature will be the data that  we will read from the state so something like that   and of course you can provide multiple options  so you can provide actually anything you want   um we can also do the following thing and  instead of providing variables one by one   we can just simply provide uh the whole state  to it right so I can do something like that   and provide just whole state and here in the  generic of the template ref we Define exactly   the context so the list of variables that might  be available and here we can say that we provide   the widget State for the content template right  so I can save it and then inside the alternative   template right here by the way let's name it  like alt widget content here in order to read the   variable I provided right here I have to use the  following syntax we Define the let like a variable   then after the dash we Define the name of this  variable that will be eventually used inside the   template yes so I can say that this is uh going  to be State and here inside the quote you have   to specify to which exactly key of the template  context object you want to get a reference in my   case I want to read this key State yeah so I can  copy it and provide it between the quotes and in   such a way I will get a reference to this  value also if you have ever worked before   with templates and context you must probably  encounter the very special key called implicit   like that and this implicit key means that it  is default value of this context which means   that you don't need to specify it explicitly like  we did or right here inside the chords and we can   and uh leave it just like that and the value with  the key explicit so means the state in our case   it will be automatically assigned to this state  variable and now I'm ready to use this variable   inside my template so I could do something like  the following so I can use the state then I could   read the data from it and I would like to read  temperature right here we go then if you don't   mind I will do the similar thing for the rest  of the properties like Sky condition and then   the same thing also for the wind so here we go and  now I can provide this alternative widget content   to the weather widget component likewise I did  it for that template header right but this time   I have to use the input content template late and  provide it as it is now if I save it look it works   perfectly and it properly reads the data that we  provided for their context yeah so we we will read   the real data Pro from the widget State because  we provided it as a context right here and this   is really cool and powerful thing all right I hope  you are still with me and I hope you enjoyed this   video and if so it is a great time to subscribe to  my YouTube channel if you didn't do it yet and hit   thumbs up to this video because it will motivate  me to create more videos like that but now let's   move forward and let's also customize this action  buttons yeah and provide the alternative view for   this part as well so I will go to the weather  widget and here I'm going to implement pretty   much the same thing like I did for the previous  two containers but this time it's going to be   the action template right and uh where it is are  here I have to create a new engine container that   also has NG template Outlet directive attached and  here we will provide the content template right or   their default widget action and we have to create  this template right we already know how to do that   we have to create NG template like that and place  those two buttons inside and also we have to give   some name for this energy template here we go  done then let's get back to the app component   and create them alternative view for this section  as well so it's going to be a new Android template   and this time here inside I want to render not  just HTML but I want to render the component and   we can't do that actually so let's generate one  I just run the following command or right here   it will generate a component for me that I can  immediately import into my app component so it is   a weather custom action component and then I can  also use it like this right then of course I would   like to apply this new template to the weather  widget so let's do it right now here we go let's   save it and you can see that my new component has  been rendered inside and now let's jump to this   new component and what I actually want to have  right here is just the one single button that   reloads the widget data and immediately copies  it so basically it it has to merge two actions   we had before but perform it in one click  so the text will be like reload and copy and   here is the question we have to somehow trigger  actions from them with weather widget component   you might think that okay this template uh where  it is uh here we go this template will be rendered   inside the weather widget component right so  it will be rendered right here so theoretically   we could try to inject the parent weather widget  component into weather custom action component   so we could do uh something like weather widget  and then inject and inject the weather widget   component and from here uh we have to create them  click listener like that and then inside this on   click Handler we could do something like weather  widget then we get access to actions right and   then we can what we have to do first reload right  and then immediately after that we copy data so   you would do something like that but if you have  a look at the console you can see that we have an   error that there is no provider for the weather  widget component this problem appears because the   apparent injector of the component that is created  inside the embedded view like we have right now   the parent injector of this component will point  out to the component where this component has   been declared and not where it is eventually  rendered so the parent injector for the weather   custom action component is the injector of the  app component and not the one from the weather   widget component so when the weather custom action  component tries to resolve their apparent weather   widget component it does the following thing it  first of all checks its own injector if there is   provider for the weather widget component it finds  nothing because there is no provider and then it   goes to the parent injector and tries to resolve  it there but in this case the parent injector   points to app component injector and app component  injector also doesn't have any provider for   um for the weather widget component and then  angular calls uh towards the whole node injector   hierarchy then it checks the environment injector  hierarchy finds nothing and then we see this error   this process I actually described very well in  the dedicated video about dependency injections   so if it is not very clear what I'm talking about  right now I would recommend you to check out that   video as well but yeah how we can solve this  issue so we can actually explicitly provide the   which injector needs to be used as a parent  for the components inside the embedded View   and we can provide it as a property for the NG  template Outlet directive so actually we could do   the following thing we can provide NG template  Outlet injector and this feature available by   the way since angular 14 so make sure that you  use angular 14 and above in order to apply this   feature and here you can provide any injector  you want you can create another one if you need   but what you actually want to do is to reuse  the current injector from the weather widget   and provide it as a parent injector for for the  components inside this embedded view so let's   um create injector property and then inject  inject injector so here we go and then I can   use this property as an argument for this input  so like that and if I save it you can see that the   error disappeared and if I click reload and copy  those actions will be executed because the weather   a custom action could properly inject the widget  component and Trigger its actions all right and   now let's very quickly recap all the key points we  have learned in this quite a long video so if you   want to declaratively render some angular template  you have to use NG template Outlet directive and   you can provide some reference to the template  that needs to be eventually rendered you can   provide templates conditionally depending of which  template needs to be rendered and it allows you to   easily customize the view of your component  and make it very flexible and extensible if   you need to provide some data for your templates  you can use them template context and pro and use   the property NG template Outlet context for it  here as a value you can provide any object you   want and this object will be available inside the  10 plate via these syntax that let Dash and then   any name of the variable and then you can specify  some exact key that needs to be assigned to this   template variable if you have a key explicit in  this context object it will be the default value   for it the next important point is that if you  render inside your template some component then   by default the parent injector for this component  will be point to them injector of the component   where this component where this template is  declared and not where it is rendered so that's   why you have to explicitly provide where it is  then injector for them for the angular template   and this injector will be eventually used as  a parent for the components that were rendered   inside this embedded View and now just a few  words about the limitations of this approach   and some so to say downsides so the first  limitation is that templates here they always   have any type they cannot be easily inferred  at least there is no official way to do that   at this point in time where when I record this  video maybe in the future it will be fixed but   uh those templates they are not strict so there  is a chance of typo and some mistakes in your   templates yeah so this is something you have to  care about yes there are some workarounds uh but   I will drop it for this video and I will rather  post it as a separate front-end snack so subscribe   to my social media profiles to not miss it and  overall you will get a lot of another useful   information from my uh short tips and tricks this  is the first kind of limitation another thing I   would like to highlight it is not a limitation  but rather downside it is their templates syntax   yeah I know a lot of developers do not like it  I also cannot say that I'm a fan of this syntax   but yeah we don't have any other Alternatives  so we have to use that I also don't like the   um this magical keyword like implicit for  the default value so it is not obvious to   me I think so I think it could be improved but  this is something you know that we just have   to accept and uh use it all right guys that's  it for today I hope this video was useful and   if so please don't forget to share it with your  colleagues and friends and don't forget to check   out my Advanced angular video courses links to  them you will find in the video description as   well as some coupon codes also please share  your thoughts in the comment section for this   video please share with me what do you think  about this feature have you ever used that if   so in which use cases maybe I forgot to mention  something I think it would be very interesting   discussion in the comments otherwise I wish you  proactive uh wait a second this video is the   last in the year two 2022 so I wish you all the  best and big success in the next upcoming 2023   so stay safe um I hope this year will be uh  better definitely better than the previous   one so uh stay healthy stay safe and see you next  year in the new video [Music] thank you [Music]
Info
Channel: Decoded Frontend
Views: 45,695
Rating: undefined out of 5
Keywords: ngtemplateoutlet angular, angular ngtemplateoutlet, ngtemplateoutlet example, ngtemplateoutletcontext, ngtemplateoutlet pass variable, ngtemplateoutlet injector, angular ng-template, angular tutorial, advanced angular tips, tutorial, rxjs, ui, angular, programming
Id: vfPVdJ2oQlM
Channel Id: undefined
Length: 35min 15sec (2115 seconds)
Published: Tue Dec 27 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.