Reactive Forms

Featured image

Reactive Forms

Making magic

Good morning! How’s it going? First of all, happy Friday, ideal for a small dose of Codeflix! Today I bring you Reactive Forms, and in particular a topic that I find very interesting and that you may have already disowned: Reusable Forms!

Reusable Forms

Well reviewing a little, usually or the most common to see and develop are usually form components. But the interesting and challenging thing is, what happens or how should we handle when we want to reuse certain parts of our forms? That they behave as nested forms and by themselves? Let’s imagine something like this:

enter image description here The idea is that instead of creating 1 single form component with all 5 controls, we make 2 components and their controls separately. This way, we can reuse the first form when we only need to embed “name, surname and email” and the second one when we need “a beer”, it’s Friday! (yes, password and confirmation che).

Why?

enter image description here

Imagine that instead of creating N forms as follows

<div [formGroup]="form">
  <label for="first-name">First Name</label>
  <input formControlName="firstName" id="first-name" />

  <label for="last-name">Last Name</label>
  <input formControlName="lastName" id="last-name" />

  <label for="email">Email</label>
  <input formControlName="email" type="email" id="email" />

  <label for="pwd">paswwordddd</label>
  <input formControlName="paswwordddd" type="password" id="password" />

  <label for="confirm">confirma el paswwordddd</label>
  <input formControlName="otropassworddd" type="passwotd" id="confirm-pwd" />
</div>

Let’s start developing only the new forms/controls, the rest we reuse because they already exist, let’s say that from the above, let’s move on to this:

<form [formGroup]="signupForm" (ngSubmit)="submit()">
  <app-profile-form [form]="signupForm"></app-profile-form>
  <app-password-form [form]="signupForm"></app-password-form>
</form>

Pretty pretty nice hugh?

enter image description here

Methods

What methods do we know of to do something like this? Well as always there is more than one way to implement this. Below I leave other ways, but today I want to show you the one that seemed to me the most neat and simple, here we go:

Method1: AddControl - Official Link

We handle the forms and their controls as parent-child, from the parent we will pass to the child by input the form of the parent and from the child to the parent we will pass a “form.addControl” to add our FormGroup (or group of controls) from the child to the parent. This way the parent form will have full control for the submit and will even receive the changes detected in each sub-form (children).

Let’s go to the COOOODEEE

Following the example of the previous form, we will have 2 components, with its 2 html and 2 TS:

<div [formGroup]="form">
  <label for="first-name">First Name</label>
  <input formControlName="firstName" id="first-name" />

  <label for="last-name">Last Name</label>
  <input formControlName="lastName" id="last-name" />

  <label for="email">Email</label>
  <input formControlName="email" type="email" id="email" />
</div>
<div [formGroup]="form">
  <label for="pwd">paswwordddd</label>
  <input formControlName="paswwordddd" type="password" id="password" />

  <label for="pwdd2">confirma el paswwordddd</label>
  <input
    formControlName="otropassworddd"
    type="password"
    id="confirm-password"
  />
</div>

and in the TS, the most important thing is that we have declared our FormGroup with its controls:

group: FormGroup;
@Input() form:  FormGroup;

   constructor  (private fb:  FormBuilder)  {}

   ngOnInit()  {

   this.group =  this.fb.group({
        firstName: ['', Validators.required],
        lastName: ['', Validators.required],
        email: ['', Validators.required]
   })}

On the other side the same, but with passwords.

this.group =  this.fb.group({
    password: ['', Validators.required],
    confirmPassword: ['', Validators.required],
    //tambien podemos usar new FormControl()
})}

This way both groups are declared only in those components, never in the parent.

And most importantly, we bind the control (our child form group) to the parent form (the one we receive via @Input():

this.form.addControl('profile', this.form);
this.form.addControl('password', this.group);

Advantages

Implementing with this method is clean, readable and simple. We avoid valueChanges OnChanges Viewchilds Outputs and Event emitters Detectionss and more changes that cost so much in performance especially subscribing to so many events and changesss no more changesss #lessonlearnt enter image description here

Other methods

And if the other methods involve everything we said before :(

Method 2

@ViewChild of our child form component, something like: (Viewchild official link)

@ViewChild(ChildComponent) childComponent: ChildComponent;

The bad thing about this is that for each value that changes the control, subscribing to the changes from the child to the parent has to be with some emitter of the valueChanges or something similar. There are many examples of how it is implemented but…. Neeeeext

Method 3 Control Value Accessor Official Link

The famous value accessorrrr, full of examples everywhere and many methods to implement it, with providers etc seems to me a lot, if it is not really necessary I would avoid it at all costs :D

I hope this is useful and happy codinggggggg!!!!