Use viewProviders
to make form controls reusable in Angular
Angular 14 brought us a great feature with reactive form typing, and it seems like life is already good… but what if I told you that form controls can be reused? It may not be a shocker for you, but this finding gave me a lot of pleasure while removing duplicate code. So, let’s go… 👉
Understanding the problem
The project deals with a calendar and several types of items (e.g. appointments, absences, reservations, etc.). A dialog window is called to create or edit each item. In the each dialog window user can select the date and time, but it is important to note that all other fields in these windows are different 😑. Of course, an abstract class was created and all the “cool” stuff, but we have 3 templates with repeating controls (date and time)… The first thing that comes to mind is to create a wrapper and write a value accessor, but another solution was found💡
Preparation
I will use version 14 of Angular and @angular/material library, so we create an empty project and create a component with an empty form.
- Create the first form control, for example, a regular text input. This control will belong directly to this component. Let’s check what we have.
2. Create a new component and template for the shared controls.
3. It’s the next step that makes all the magic ✨. We need to add the viewProviders
(not providers
) property to the component metadata with the following value:
The important thing here: Angular is using the @Host()
resolution modifier for the parent ControlContainer
(Checkout Angular source code: FormControlName Directive), that doen’t allow you to look to the providers
, that’s why we need to use viewProviders
.
4. Using DI, we inject the parent container into the component. We can pass dynamic values from the parent to the child component using @Input
. Do not forget to delete added controls on ngOnDestroy.
5. Now we can use the newly created component with shared controls in the parent form’s template. Let’s check what we have now.
It works! 🪄
Conclusion
- We have created a reusable generic form control
- Parent form has all the knowledge about all controls
- Once again, we’ve seen that DI is something incredible
Hope this can help! Share your thoughts too!