How to Make Forms in Angular REUSABLE (Advanced, 2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi. It's time for the deep dive into angular forms and in this video I'm going to show you how you can reuse your form control or the group of form controls By extracting them into a separate component and then reuse this component in other angular forms in your angular Application if you try to do it before probably, you know that it is not as easy as it seems If you continue watching, you will see in action a couple of quite rare Angular features like host resolution modifier and view providers. And besides that, we will dive into a source code of Angular forms to understand a little bit more about How they were designed and how they work under the hood and there we will actually find the key to Usable forms. My name is Dmytro Mezhenskyi and on my youtube channel, you can find already hundreds hundreds of advanced and unique angular tutorials So subscribe right now, continue watching, and let's learn more about Angular forms. First of all, I would like to mention that And everything you will learn in this tutorial, and you will learn quite a lot. This is just a tiny part of my entire in depth video course about Angular forms. And later in this video, I will show you exactly what you will learn from there and which really complex form controls you will be able to build out of the course. But now let's focus on our concrete use case and let's learn how to make form controls reusable in your Angular applications. So here I've got a very simple form that consists of three form controls and two of them, they are grouped within the nested form group called delivery address. And here you can see the HTML of this form. You can see I use reactive forms for that. Here's the form group, which represents the root form group. And here. display name form control, the delivery address form group and two nested form controls inside. And this is how looks the form model for this concrete form. So as you can see, very simple, regular, reactive form. Now imagine that your goal is to reuse this entire address form group inside Another form. So basically you want to exclude it into a separate component and include this component In every form where you need this address form group, right? So what you would do in this case most probably you would take this whole form group and exclude it from This template and you would create some another component like I did it right now and you would place this whole template here, just like that, right? Then you would need to import also reactive forms module to make it work. And then you would need to go to the app component and also import these address group component. And instead of the previous. Uh, form group, you would use this app address group component just like that, right? But let's save, uh, this change and have a look at the console of our browser. And there we see the following error. So the form group name must be used within a parent form group directive. You will want to add blah, blah, blah, blah, blah, and so on. So the general idea of this message is that the form group directive has to be used within the same view with the form group name directive. So it means that we can solve this problem by applying the form group directive within This child component and provide the root form group as a argument for this form group directive So it would look like this. So here's my form group directive and we have to wrap this everything with this form group, right and we have to provide the root form group as a Input parameters, so I would create some input here, call it form and say that it is going to be the form Group, and of course I have to go back and provide this form Just like that, right? And now if I reload the page You can see the error has disappeared and my form is works. But guys, look, just look at this. Look at this. This is also the terrible part because we have to always propagate the parent form group down to the child. Um, we need a lot of boilerplate to make this form just working. And it would be so cool if we could get rid of all this stuff, remove this and also this input. Why we cannot just make it work, why do we need to do a lot of these unnecessary actions? And here I will show you the solution, but for that we have to investigate the source code a little bit and figure out how it actually works. So welcome to the source code of the form group named directive. As you can see, it is just a regular form. Angular directive, right? So there is no magic inside Angular forms actually. And, uh, the problem actually in this line, what this line is doing. So in order to properly work the form group name directive, when it is being initialized, it has to register its own instance. Inside the parent control container the control container. This is the payments injection provider token that points to Other directive instances that are responsible for the, uh, form control grouping. If we're talking about reactive forms, those are, uh, form group name directive, form group directive, and form array name directive. If we're talking about template driven forms. This is ngModelGroupDirective And this binding of the provider token and concrete directive instance happens by configuring the providers As you can see here, there is provided control container token that points to the instance of the form group name directive Alright, and if you have a look at some other directive that is responsible for controls grouping There you can find a similar provider where the control container token provided and it points to this time to the form group directive instance right okay i hope this part is pretty much clear and now let's very quickly talk how the control container is being resolved so here you can see a group of resolution modifiers the skip self resolution modifier instructs angular that it has to start looking for the control container provider starting from the parent injector, not from the injector of this directive, because otherwise you will get the circular dependency, but starting from the parent one. The host resolution modifier is very tricky and it tells that Angular should look for the provider for the control container within the same template. Where this form group name directive is used a bit tricky. Yeah, I know So that's why let's go back to our project and let me revert back our Working solution with the form group rubber So what happened why it was working this solution because here's the form group name directive This is the one which source code we just investigated and then it tries to inject their control container from the closest parent injector. The closest parent injector will be the injector of the form group directive. And this injector has the provider for the control container. And because, uh, this injector is located within the same. template within the same view, that's why the form group name properly resolves the parent control container. But when we remove it like that, in this case the closest injector that contains the provider for control container is inside the form group directive that is used in the app component view. But the host resolution modifier says, uh, uh, uh, You are not allowed to inject control container that is located outside of the view Where the current directive instance has been created So that's why this form group name directive doesn't see the control container provider From the app component view and that's why it fails. Phew, I have been recording this part almost So I really hope that you understood how this everything works, but yeah, let's move forward. So basically to solve our problem, we have to provide the control container for address group component that points to the parent control container. And it has to be done within the view of the address group component. So, how we can do that? You could think that we could configure providers property right here. So, let's try. I use providers. Here I provide the object. Where I define the provide here. This is going to be the control. container, right? And, um, and the value of it has to be that parent container. So for that, I would use the useFactoryDependencyProvider. And this is the function where I can actually inject the control container, but I will use also skipSelfResolutionModifier. But as you can see, it still doesn't work. We still have the same issue. And this is again because of the host resolution modifier. Because host resolution modifier doesn't even allow you to look into providers inside that same component. And that's why we have to use a Quite rare feature in Angular and namely we have to use ViewProviders Because this is the last place where the HostResolutionModifier can look for providers All right, and if we save it right now, you can see that the error has disappeared and Our form remains working. So finally, congratulations. We got read from the boilerplate here and there. We got read from the input. We just use the view provider that can provide a control container token for the directives here inside this template. Beautiful, but we still have a little problem. And currently the issue is that the functionality is kind of Split between two components inside. Address group component, we have the view part, but the model that relates to this form, namely this one, it is located in separate component. It would be great if we could keep everything in one place and if the address group could register the proper form control models. Right? So how can we do that? Well, we can again use the control container that we can inject. So let's inject the control container. And in this control container, I'm interested in the corresponding instance of the Form group model. So let's create a dedicated getter. Let's name it like parent form group. Doesn't matter. And it will return parent container and namely the control property and let's cast it as a form group. It is pretty safe to do that because the control of the control container will be always that form group. And the form group provides you a set of methods that allow you to add or remove some certain form control instances from this group. So once the address group component is being initialized, so let's use the ngOnInit lifecycle hook, and here, after the initialization, We will use this parent form group in order to add the new control and which control we are going to add we are going to add exactly this part so we can completely cut it from here and just go and place it right here and i have to just uh fix it a little bit so it is going to be the name of the control right and the second argument it is the values, which exactly, uh, FormControl or FormControlGroup we have to register. And in my case, it will be the FormGroup with addresses. And of course, I have to import the FormControl model right here. And this is it. So if I save everything, you can see that everything works fine. but also don't forget that this component can be destroyed so you have to handle also this case and for that let's use the ngOnDestroy lifecycle hook and the similar way we just remove control and we say that we will remove exactly This control, right? So here we go. And as you can see, uh, my form still works. And if I type some stuff here and try to submit it, you can see that delivery address was hooked up and added. To this form group, even though we don't declare it right here, it happens automatically when the address group component is being initialized, but we can go even further and make it not that hard coded, but make it. really dynamic and for that we can introduce a couple of inputs the first one can be like ctrl key that is empty string and we can also make it required in the latest angular version you can configure input as a required which is really cool and useful and then this ctrl key we use in Instead of these strings, just like that, it means that we can configure their control key just like a regular input. This is the, this is the delivery address, right? And we can also provide something like label, right? So here we can configure the string as well. So let's do a new input and it's going to be a label. It is not required by default. It's just an empty string and we will use this label where we will use it right here So here we go And now we can do what we can provide this label as an input as well So in my case, it is a delivery address right, I save it and it remains working and every time when you have to reuse this address group you Just have to add it and it will be For example, I could have a use case when I want to reuse the same group within even the same form, because often we provide their delivery address, right? And we have something like a billing address, right? And usually they're identical. And, uh, here I just have to adjust the label and obviously their control key and change it to billing address. And I save it. And imagine that user fills the form. South Metro, zip code is 111, street is FFFFF, billing address will be zip code 22222, and street, I don't know, MMMMM, whatever. And now I submit the form and you can see that both billing address... Okay, billing address didn't work. Ah, I got it because we hard coded delivery address here. So I have to use my input control key. I have to use it instead the hard coded string. Okay, now the metro. 1111, FFFFF, 2222222, MMMMMMM. And... Submit, and now you can see everything works, billing address works, delivery address works, display name works. Super simple, super flexible, super cool. You can now reuse this address group everywhere in your application. It is magically hooked up and adds and registers everything it needs for its work. Really reusable form group. And as I said... This is just a small part of my entire work. In depth angular form course and take just one minute to have a look what you will build in the end of this course, in just a few easy sections, you will be guided through most of the template driven and reactive forms features, so you can create two advanced and interactive forms that will impress. everyone and leave you feel proud of your work. But that's not all. The course strongly focuses on custom form controls implementation, so you will learn a lot about control value accessor and how it is used by Angular under the hood. You will get to build custom form controls like a rating picker and a simple text editor, both of which support template driven and reactive forms, as well as, you know, validations and other form control features, of course. In addition, you will master a really complex component in the third section. Here I'm talking about a drop down component that supports option filtering, multi selection, and accessible keyboard navigation. With my Step by step guidance, you will be able to build this advanced form control very easy. Already impressive, isn't it? But even that is not all. In the remaining course sections, you will learn how to create Angular forms dynamically from JSON config and which architecture solution can help make it scalable and maintainable in the future. In the last section, you will learn how to manage validation errors globally, so you can dynamically render error messages for invalid controls without generating a ton of boilerplate in your component templates. So, enroll right now and let's take your form building skills to a completely new level. The link to the course and discounts will be in the video description. All right guys, thanks for watching. I hope this video was really useful, and if so, and if you'd like to help me to grow my YouTube channel, one of the easiest and best ways to help me with that is to share this video with your colleagues and friends. Or you can make a little donation by using this square code that should appear somewhere on the screen. Here and starting from the next video in the end. I will be showing the nicknames of those who Supported my youtube channel and maybe in the future. I will even create some private community from it with some unique content. What do you think about that? Please let me know in the comment section. Otherwise, I wish you productive week ahead, guys. Stay safe and see you in the next Advanced Angular tutorial.
Info
Channel: Decoded Frontend
Views: 49,070
Rating: undefined out of 5
Keywords: forms in angular, reusable forms in angular, angular reactive forms, reusable angular component, angular reusable, angular reusable form component, angular reusable form input component, angular 2023, advanced angular tips, Angular tutorial, rxjs, angular development, Decoded frontend, web development 2023, coding tutorial
Id: o74WSoJxGPI
Channel Id: undefined
Length: 21min 10sec (1270 seconds)
Published: Wed Sep 20 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.