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

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


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

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. We will cover all available features like creating views from templates, providing template context data, and controlling the proper Angular Dependency Injection flow. So if you watch the video until the end, you can be sure that you will be able to handle 80% of all possible use cases related to component view customization.

💥 Become a PRO with my in-depth Angular Forms Course💥
🔗 10% discount for the first 10 students - https://bit.ly/advanced-ng-forms-disc

🕒 Time Codes:
00:00:00 - Intro;
00:00:58 - Project Overview;
00:03:17 - Describing the Problem;
00:04:49 - How to create Embedded Views in Angular;
00:10:54 - Let’s meet [ngTemplateOutlet] directive;
00:12:43 - Conditionally Rendering ng-templates;
00:16:38 - Introducing Template Context;
00:24:01 - Controlling Parent Injector for components in NgTemplates;
00:30:09 - Recap things we learned;
00:32:14 - Disadvantages of [ngTemplateOutlet] directive;
00:34:00 - Outro;

🔗 Project Code on GitHub:
https://github.com/DMezhenskyi/angula… (initial state in main branch)

🙌 Support Dmytro https://bit.ly/donate-to-decoded-fron

💡 Short Frontend Snacks (Tips) every week here:
Twitter - https://twitter.com/DecodedFrontend
Instagram - https://www.instagram.com/decodedfron
LinkedIn - https://www.linkedin.com/in/dmezhenskyi

#ng #angular #angular15


Content

0 -> this video will teach you how to utilize an  angular ngTemplateOutlet directive to  
5.64 -> create reusable components with customizable  and extensible Views you will learn everything  
11.22 -> you have to know about this directive because  I'm going to cover all its available features  
16.38 -> like creating views from angular templates how to  provide template context data and how to control  
23.76 -> the proper angular dependence injection flow in  the embedded views so if you watch this video  
30.06 -> Until the End, you can be sure that you will be  able to solve 80% of use cases where you  
37.38 -> need to implement customizable view for your  angular components if you have first time on  
42.78 -> my channel my name is Dmytro Mezhenskyi and here  you can find a lot of advanced angular tutorials  
48.18 -> and courses you can check them out later but  now let's get started and enjoy this video
58.56 -> all right let's get started and let me very  quickly onboard you and demonstrate the current  
65.16 -> application what kind of problems this application  has and how we are going to fix those problems  
73.26 -> uh so as you can see I've got some angular  component that renders the weather forecast and  
81.24 -> it also has couple of buttons that perform some  action so we can refresh data of this widget and  
88.8 -> we can copy information to our clipboard in order  to you know paste it somewhere of course all this  
96.54 -> data and actions those are mocked data I didn't  want to bring the real implementation because I  
103.86 -> wanted to keep stuff simple um so yeah this is  how it looks like and there is our component  
111.72 -> rendered right here and here you can see the  implementation of this component as you can see  
117.9 -> pretty straightforward we have just some template  that renders some data this data comes from some  
126.12 -> certain State this state is represented as a separate service that is provided on the  
134.16 -> for the injector of the wizard  weather widget which means that  
140.46 -> uh those Services they will be single tones in  scope of this component and all its children right  
150.42 -> the same for widget actions uh widget actions  those are set of uh just mocked services that  
159 -> supposed to perform some useful actions and uh  yeah this is how it looks like you can see pretty  
166.32 -> straightforward widget state is also very very  simple and what is what else I am this inject  
175.56 -> function for those who just started with angular  this is same as an injection via Constructor so  
183.3 -> you could see probably the construction like  this one right and this is pretty much the  
190.38 -> same as this notation right this is just a new  way to do that all right and now let's quickly  
198.24 -> talk about problems and limitations the problem  has and actually the biggest problem here is the  
205.14 -> component template because if you have a look  at it you can easily notice that that template  
211.86 -> is completely hard coded and you cannot change  it you cannot customize it and it might be a big  
219.06 -> problem if you decide to distribute this component  as a part of some component library or if you need  
226.2 -> to reuse this component in in other part of your  application but you have to change somehow look  
232.2 -> and feel of this component it is not possible  and it is a problem and I'm going to tell you in  
238.44 -> advance that there are a couple of ways of how to  customize the view of angular components the first  
244.74 -> way is to use NG template oh sorry NG content  directive it is also known as a Content projection  
251.64 -> and another approach is to create embedded view  from angular templates and this is exactly the  
258.3 -> approach I'm going to use in this video because  I find it a bit more flexible compared to content  
265.92 -> projection but if you'd like to learn more about  content projection as well uh please let me know  
272.1 -> about that in the comments under this video and  hit thumbs up if I uh get enough let's say 1  
279.6 -> 000 likes under this video I will recognize that  this topic might be interesting for you and I will  
285.18 -> create a dedicated uh video about that but now  let's move forward let's move forward and let's  
291.12 -> quickly talk about how do we create uh embedded  views in angular so in order to create embedded  
298.8 -> view in angular we need to have basically  two things we have to have some container  
305.1 -> it's kind of Encore where exactly in the view  needs to be rendered there embedded View and  
313.98 -> then we have to have the template that needs to  be instantiated and eventually rendered right  
320.58 -> right so the container can be actually any HTML  note yeah we could create some another div and  
330.42 -> Market as a container using the template variable  yeah and if we want to create angular template  
338.34 -> from some piece of HTML code then we have to use  the NG template and place the HTML that is going  
347.46 -> to be the angular template right between those  two tags and what is interesting about NG template  
354.36 -> is that it is lazy so if I save it right now you  can see that everything disappeared it is because  
362.88 -> we have to explicitly create the view from this  template and only then it will be visible so how  
371.52 -> we usually create the embedded view in order to do  that we have to get reference to those two things  
378.6 -> to the container and to the NG template so let  maybe name it as a as a default widget header and  
386.7 -> then we can easily get reference to them by using  the huge child decorator so I get reference first  
394.62 -> to the container and here is very important thing  if I leave it as it is then I will get reference  
403.32 -> to the native div element and this is not what I'm  going to achieve I want to read from here the view  
411.3 -> container ref right and if I want to get reference  to it I have to specify the config object for the  
418.74 -> view child and provide here the read property and  say what exactly I want to read from this node and  
425.76 -> from here I'm going to read The View container ref  like that so here I have to create a property here  
433.74 -> we go and it's going to be the instance of view  container ref obviously right and then I have to  
440.1 -> do the similar thing for the default widget header  so let's create another view child get a reference  
448.8 -> to the default widget header template here I  don't need to specify anything because I need  
454.2 -> to gather a direct reference to the NG template  right so let's name it header template and it's  
461.64 -> going to be the template reference reference to  the template right and let it be any for now we  
470.22 -> will talk about this type later in this video but  it is not enough those two just references right  
478.26 -> and because we get references using view child it  means that those guys they will be available only  
485.76 -> when the component view is instantiated and we  have a dedicated lifecycle hook for that called  
492.42 -> and G after view in it right and inside this  lifecycle hook uh those guys as I said will be  
500.28 -> available so I can use my container right and call  the method create embedded View and this method  
509.34 -> expects that template that needs to be rendered  and I already have such a reference and it is  
516 -> a header template property so like that and if I  save it right now you can see that the header view  
524.52 -> is back and let's have a look how it looks in the  HTML so here is the our widget header and this is  
533.88 -> the container right this is exactly this div and  next to the container there were they were Android  
541.2 -> widget title and widget subtitle and those guys  they are coming from the angular template that  
547.44 -> we created before I know you might be slightly  confused because you probably expected that the  
554.04 -> template will be rendered inside the container  right but no it will be rendered next to them  
561.06 -> container node and if you want to get read from  this HTML tag you can always use such a thing  
570.66 -> called NG container and in this case you can see  that that empty div has disappeared because any  
579.18 -> container it is being rendered eventually into  nothing yeah it works just like a placeholder  
586.14 -> for some HTML notes but let's quickly get back  to our current implementation and the way we  
593.58 -> implemented this feature right now it is so  called declarative Paradigm in programming  
600.24 -> because we explicitly specify steps that needs to  be performed in order to get some desired result  
608.28 -> yeah so we say that okay get a reference to The  Container get the reference to the header template  
614.88 -> then inside NG after view you need lifecycle hook  create the embedded view blah blah blah blah blah  
621.24 -> so we describe how things needs to be done from  Another Side there exists declarative parting  
629.64 -> that describes what needs to be done for instance  I need to have embed that you created so here is  
637.08 -> the template please create it I don't care how it  will be done I just need the final result so this  
643.98 -> is the declarity of uh Paradigm in programming and  usually declarative programming is more readable  
652.32 -> and easier to understand and in order to implement  this current feature we have right now but using  
660.9 -> a declarative way we have to use NG template  Outlet directive that allows us to do that so  
669.96 -> finally we started to talk about this directive  because I don't want just to show the feature I  
676.38 -> want to teach you why this feature exists and  which problems does it solve so how it would  
683.64 -> look like when we apply the NG template Outlet  directly so I can completely remove this stuff  
689.64 -> then we obviously have to import this directive  yes so let's do that so I type NG template Outlet  
697.08 -> or you could inject also a common model it is part  of the common model but yeah as you want and once  
703.8 -> we have this directive imported we can apply  it to our NG container just like that and as a  
710.7 -> value for it we have to provide a reference to the  template that needs to be eventually rendered so  
717.3 -> like that and as you can see it works the same  way but it is more readable and less code needed  
726.3 -> in order to achieve the same goal and I can also  remove all those stuff as well nice and there is  
733.44 -> no any magic here actually under the hood if we  have a look at the source code of this directive  
739.26 -> you can see that it does pretty much the same  yeah it has more like conditions whatever but  
745.26 -> eventually it has also view container ref  and it creates embedded View and provides  
750.9 -> the template that needs to be rendered and then  context injector like those stuff we will cover  
757.74 -> late in this video but in a nutshell it is pretty  much the same what we have implemented just couple  
763.38 -> of minutes ago all right now what benefits we can  get from refactoring our code to using a template  
772.38 -> Outlet Plus uh angular template it means that here  we can dynamically provide any template we want we  
784.32 -> can allow user to provide alternative templates we  can do it by using just regular inputs so I create  
792 -> some separate input I name it like header template  I say that it needs to be the template ref again  
799.98 -> so far it is any type and having that I can just  do something like that I can say that okay render  
808.92 -> the template that user provided via component  input or if it's not provided then use default  
817.02 -> widget header as a fallback and that's it so I  can save it you can see that nothing has changed  
823.92 -> but now I can go to app component and create some  new NG template and I can say here that this is  
833.28 -> some alternative widget header and there inside I  can play some alternative template right so I can  
841.14 -> create something like that and here play something  like today's weather yeah and then the reference  
847.68 -> to this template I can easily provide via this new  header template input just like that and if I save  
856.08 -> it right now you can see that the header got the  new template that was provided from outside so  
864.06 -> we replaced the default header with the new one  and if I remove this input from here it will fall  
872.46 -> back to the default one right so this is the first  cool thing that you can Implement using ng10 blade  
880.02 -> Outlet directive and yeah another thing I forgot  to say about the style so most probably you want  
886.08 -> to apply some styles for this new alternative  template you can Define Styles in the component  
892.44 -> where this template is declared so I declare  it inside app components so somewhere here I  
899.28 -> can place the styles for my alternative header  right and if I save it those styles were applied  
907.32 -> so let me close this and let's move forward to the  next feature so imagine that we have to we want  
916.08 -> to implement the same thing but for our widget  content so let's get started to do that so I would  
923.82 -> need to duplicate this input right and just maybe  rename it so I say that this is content template  
932.28 -> and then I have to create a similar construction  for a video template as well so I create NG  
941.34 -> container where I also apply the NG template  Outlet directive right and there I have to  
950.04 -> create also the templates so let's create another  NG template like that and I say that this is the  
957.48 -> default widget content like that and this engine  template should wrap this HTML so here we go  
967.56 -> uh what I forgot I forgot to provide actually  values to the ntng template Outlet directive so  
974.58 -> I say that it needs to take other content template  provided from user or it should have a fullback  
983.58 -> that points to this engine template so here we go  then in order to provide the alternative content  
990.36 -> view for this widget you probably uh go to the  app component you are going to create a new NG  
998.22 -> template you are very excited that finally  we'll customize this component you start to  
1004.16 -> bring some new alternative view but then you are  quickly realize that okay you need to render the  
1012.86 -> temperature but where we will take this data  so here it is pretty much Clear yeah we get it  
1019.64 -> from the state uh this is the property of this  component but here we don't actually have the X  
1027.5 -> s to this data one of your suggestions could be  like okay we could get actually the reference  
1035.06 -> to the weather widget component instance using  uh view child decorator right and once we get  
1041.12 -> the reference we could simply read the state  property from the component and then render the  
1048.86 -> value we need inside the alternative template  the solution would theoretically work and in  
1055.88 -> practice it would also work but this solution  is quite terrible because imagine that you have  
1062.78 -> not only one weather widget here but you have I  know dozens of them then you would need to get  
1068.18 -> reference to all of them track if you properly  resolve States for each of this weather widget  
1076.04 -> instances also you might have them implementation  of the component where the state is protected or  
1083.9 -> private then even even if you get a reference  to it you will not be able to read this property  
1090.44 -> because it is just protected yeah so this solution  isn't the best one and let me show you another one  
1097.7 -> that works perfectly for that and this is where  NG template Outlet context property comes into  
1105.14 -> the play and template context it is nothing  else as Chester data that is available for  
1114.26 -> some particular angular template and in order  to provide this data to that template we have  
1122.36 -> to use a special property of the NG template  Outlet directive and it is simply called NG  
1129.44 -> template Outlet context and as I said it is just  the data which can be represented as object and  
1137.3 -> we can say that for this template that can be  available a variable like temperature and their  
1147.08 -> value for the temperature will be the data that  we will read from the state so something like that  
1156.08 -> and of course you can provide multiple options  so you can provide actually anything you want  
1162.44 -> um we can also do the following thing and  instead of providing variables one by one  
1167.78 -> we can just simply provide uh the whole state  to it right so I can do something like that  
1175.52 -> and provide just whole state and here in the  generic of the template ref we Define exactly  
1183.44 -> the context so the list of variables that might  be available and here we can say that we provide  
1189.68 -> the widget State for the content template right  so I can save it and then inside the alternative  
1198.68 -> template right here by the way let's name it  like alt widget content here in order to read the  
1207.68 -> variable I provided right here I have to use the  following syntax we Define the let like a variable  
1215.72 -> then after the dash we Define the name of this  variable that will be eventually used inside the  
1223.22 -> template yes so I can say that this is uh going  to be State and here inside the quote you have  
1230.18 -> to specify to which exactly key of the template  context object you want to get a reference in my  
1238.4 -> case I want to read this key State yeah so I can  copy it and provide it between the quotes and in  
1247.16 -> such a way I will get a reference to this  value also if you have ever worked before  
1253.52 -> with templates and context you must probably  encounter the very special key called implicit  
1260.84 -> like that and this implicit key means that it  is default value of this context which means  
1268.52 -> that you don't need to specify it explicitly like  we did or right here inside the chords and we can  
1275.66 -> and uh leave it just like that and the value with  the key explicit so means the state in our case  
1283.76 -> it will be automatically assigned to this state  variable and now I'm ready to use this variable  
1291.56 -> inside my template so I could do something like  the following so I can use the state then I could  
1301.28 -> read the data from it and I would like to read  temperature right here we go then if you don't  
1306.98 -> mind I will do the similar thing for the rest  of the properties like Sky condition and then  
1315.74 -> the same thing also for the wind so here we go and  now I can provide this alternative widget content  
1324.08 -> to the weather widget component likewise I did  it for that template header right but this time  
1332.12 -> I have to use the input content template late and  provide it as it is now if I save it look it works  
1341.66 -> perfectly and it properly reads the data that we  provided for their context yeah so we we will read  
1350.42 -> the real data Pro from the widget State because  we provided it as a context right here and this  
1359.66 -> is really cool and powerful thing all right I hope  you are still with me and I hope you enjoyed this  
1365.96 -> video and if so it is a great time to subscribe to  my YouTube channel if you didn't do it yet and hit  
1371.78 -> thumbs up to this video because it will motivate  me to create more videos like that but now let's  
1378.92 -> move forward and let's also customize this action  buttons yeah and provide the alternative view for  
1387.86 -> this part as well so I will go to the weather  widget and here I'm going to implement pretty  
1393.74 -> much the same thing like I did for the previous  two containers but this time it's going to be  
1400.76 -> the action template right and uh where it is are  here I have to create a new engine container that  
1410.66 -> also has NG template Outlet directive attached and  here we will provide the content template right or  
1419.96 -> their default widget action and we have to create  this template right we already know how to do that  
1428.18 -> we have to create NG template like that and place  those two buttons inside and also we have to give  
1438.68 -> some name for this energy template here we go  done then let's get back to the app component  
1446.12 -> and create them alternative view for this section  as well so it's going to be a new Android template  
1454.64 -> and this time here inside I want to render not  just HTML but I want to render the component and  
1463.1 -> we can't do that actually so let's generate one  I just run the following command or right here  
1470.18 -> it will generate a component for me that I can  immediately import into my app component so it is  
1477.08 -> a weather custom action component and then I can  also use it like this right then of course I would  
1486.2 -> like to apply this new template to the weather  widget so let's do it right now here we go let's  
1497.18 -> save it and you can see that my new component has  been rendered inside and now let's jump to this  
1504.08 -> new component and what I actually want to have  right here is just the one single button that  
1512.24 -> reloads the widget data and immediately copies  it so basically it it has to merge two actions  
1521.48 -> we had before but perform it in one click  so the text will be like reload and copy and  
1530.06 -> here is the question we have to somehow trigger  actions from them with weather widget component  
1541.28 -> you might think that okay this template uh where  it is uh here we go this template will be rendered  
1551 -> inside the weather widget component right so  it will be rendered right here so theoretically  
1559.88 -> we could try to inject the parent weather widget  component into weather custom action component  
1571.1 -> so we could do uh something like weather widget  and then inject and inject the weather widget  
1579.08 -> component and from here uh we have to create them  click listener like that and then inside this on  
1590 -> click Handler we could do something like weather  widget then we get access to actions right and  
1599.36 -> then we can what we have to do first reload right  and then immediately after that we copy data so  
1608.6 -> you would do something like that but if you have  a look at the console you can see that we have an  
1616.7 -> error that there is no provider for the weather  widget component this problem appears because the  
1623.72 -> apparent injector of the component that is created  inside the embedded view like we have right now  
1632.18 -> the parent injector of this component will point  out to the component where this component has  
1640.16 -> been declared and not where it is eventually  rendered so the parent injector for the weather  
1647.42 -> custom action component is the injector of the  app component and not the one from the weather  
1656 -> widget component so when the weather custom action  component tries to resolve their apparent weather  
1663.08 -> widget component it does the following thing it  first of all checks its own injector if there is  
1669.68 -> provider for the weather widget component it finds  nothing because there is no provider and then it  
1676.88 -> goes to the parent injector and tries to resolve  it there but in this case the parent injector  
1684.74 -> points to app component injector and app component  injector also doesn't have any provider for  
1693.26 -> um for the weather widget component and then  angular calls uh towards the whole node injector  
1700.1 -> hierarchy then it checks the environment injector  hierarchy finds nothing and then we see this error  
1706.46 -> this process I actually described very well in  the dedicated video about dependency injections  
1712.4 -> so if it is not very clear what I'm talking about  right now I would recommend you to check out that  
1718.28 -> video as well but yeah how we can solve this  issue so we can actually explicitly provide the  
1726.98 -> which injector needs to be used as a parent  for the components inside the embedded View  
1733.34 -> and we can provide it as a property for the NG  template Outlet directive so actually we could do  
1741.26 -> the following thing we can provide NG template  Outlet injector and this feature available by  
1749.24 -> the way since angular 14 so make sure that you  use angular 14 and above in order to apply this  
1754.94 -> feature and here you can provide any injector  you want you can create another one if you need  
1761.66 -> but what you actually want to do is to reuse  the current injector from the weather widget  
1767.84 -> and provide it as a parent injector for for the  components inside this embedded view so let's  
1776.54 -> um create injector property and then inject  inject injector so here we go and then I can  
1784.82 -> use this property as an argument for this input  so like that and if I save it you can see that the  
1792.86 -> error disappeared and if I click reload and copy  those actions will be executed because the weather  
1801.2 -> a custom action could properly inject the widget  component and Trigger its actions all right and  
1810.56 -> now let's very quickly recap all the key points we  have learned in this quite a long video so if you  
1818.54 -> want to declaratively render some angular template  you have to use NG template Outlet directive and  
1825.86 -> you can provide some reference to the template  that needs to be eventually rendered you can  
1832.16 -> provide templates conditionally depending of which  template needs to be rendered and it allows you to  
1839.36 -> easily customize the view of your component  and make it very flexible and extensible if  
1847.76 -> you need to provide some data for your templates  you can use them template context and pro and use  
1856.82 -> the property NG template Outlet context for it  here as a value you can provide any object you  
1865.04 -> want and this object will be available inside the  10 plate via these syntax that let Dash and then  
1876.02 -> any name of the variable and then you can specify  some exact key that needs to be assigned to this  
1884.78 -> template variable if you have a key explicit in  this context object it will be the default value  
1892.7 -> for it the next important point is that if you  render inside your template some component then  
1900.98 -> by default the parent injector for this component  will be point to them injector of the component  
1909.14 -> where this component where this template is  declared and not where it is rendered so that's  
1916.52 -> why you have to explicitly provide where it is  then injector for them for the angular template  
1925.76 -> and this injector will be eventually used as  a parent for the components that were rendered  
1933.26 -> inside this embedded View and now just a few  words about the limitations of this approach  
1939.02 -> and some so to say downsides so the first  limitation is that templates here they always  
1947.66 -> have any type they cannot be easily inferred  at least there is no official way to do that  
1955.4 -> at this point in time where when I record this  video maybe in the future it will be fixed but  
1962.3 -> uh those templates they are not strict so there  is a chance of typo and some mistakes in your  
1970.64 -> templates yeah so this is something you have to  care about yes there are some workarounds uh but  
1977.84 -> I will drop it for this video and I will rather  post it as a separate front-end snack so subscribe  
1984.8 -> to my social media profiles to not miss it and  overall you will get a lot of another useful  
1991.34 -> information from my uh short tips and tricks this  is the first kind of limitation another thing I  
1998.96 -> would like to highlight it is not a limitation  but rather downside it is their templates syntax  
2006.94 -> yeah I know a lot of developers do not like it  I also cannot say that I'm a fan of this syntax  
2014.08 -> but yeah we don't have any other Alternatives  so we have to use that I also don't like the  
2023.14 -> um this magical keyword like implicit for  the default value so it is not obvious to  
2031.9 -> me I think so I think it could be improved but  this is something you know that we just have  
2038.38 -> to accept and uh use it all right guys that's  it for today I hope this video was useful and  
2045.4 -> if so please don't forget to share it with your  colleagues and friends and don't forget to check  
2050.32 -> out my Advanced angular video courses links to  them you will find in the video description as  
2056.5 -> well as some coupon codes also please share  your thoughts in the comment section for this  
2061.6 -> video please share with me what do you think  about this feature have you ever used that if  
2067.18 -> so in which use cases maybe I forgot to mention  something I think it would be very interesting  
2072.76 -> discussion in the comments otherwise I wish you  proactive uh wait a second this video is the  
2080.08 -> last in the year two 2022 so I wish you all the  best and big success in the next upcoming 2023  
2091.54 -> so stay safe um I hope this year will be uh  better definitely better than the previous  
2098.62 -> one so uh stay healthy stay safe and see you next  year in the new video [Music] thank you [Music]

Source: https://www.youtube.com/watch?v=vfPVdJ2oQlM