Reactive Forms

Featured image

Reactive Forms

Haciendo magia

Buenasss! Como andan?! Antes que nada felíz viernes, ideal para una pequeñísima dosis de Codeflix! Hoy les traigo Reactive Forms, y en particular un tema que me parece muy interesante y con el que quizas ya renegaste: Reusable Forms!

Reusable Forms

Bueno repasando un poco, por lo general o lo mas comun de ver y desarrollar suelen ser componentes de formularios. Pero lo interesante y desafiante es, que pasa o como debemos manejarnos cuando queremos reutilizar ciertas partes de nuestros formularios? Que se comporten como formularios anidados y por si solos? Imaginemos algo asi:

enter image description here La idea es que en vez de crear 1 solo componente formulario con todos los 5 controles, hagamos 2 componentes y sus controles por separado. De esta forma, podremos reutilizar el primer form cuando solo necesitemos embeber “nombre, apellido y email” y el segundo cuando necesitemos “una birra”, es viernes! (si, contraseña y confirmacion che).

¿Por qué?

enter image description here

Imaginen que en lugar de crear N formularios asi

<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>

Comencemos a desarrollar solo los formularios/controles nuevos, el resto los reutilizamos porque ya existen, digamos que de lo anterior, pasemos a esto:

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

Queda fachera facherita no?

enter image description here

Metodos

Que metodos conocemos para hacer algo asi? Bueno como siempre hay mas de una forma de implementar esto. Mas abajo dejo otras formas, pero hoy quiero mostrarles la que mas prolija y simple me parecio a mi, ahi vamos:

Metodo1: AddControl - Link oficial

Manejamos los formularios y sus controles como padre-hijo, desde el padre le pasaremos al hijo por input el form del padre y desde el hijo al padre le pasaremos un “form.addControl” para agregar nuestro FormGroup (o grupo de controles) del hijo hacia el padre. De esta forma el form padre tendra pleno control para el submit e incluso recibira los cambios detectados en cada sub-form (hijos).

Vamos al cooooodigoooooo

Siguiendo el ejemplo del form anterior, tendremos 2 componentes, con sus 2 html y 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>

y en los TS, lo mas importante es que tengamos declarado nuestros FormGroup con sus controles:

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

       constructor  (private fb:  FormBuilder)  {}

       ngOnInit()  {

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

Del otro lado lo mismo, pero con las contraseñas

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

De esta forma ambos groups quedan declarados solo en esos componentes, nunca en el padre.

Y lo mas importante, bindeamos el control (nuestro form group del hijo) hacia el form padre (el que recibimos via @Input():

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

Ventajas

Implementarlo con este metodo es limpio, legible y sencillo. Nos evitamos los valueChanges OnChanges Viewchilds Outputs y Event emitters Detectionss y mas changes que tanto cuesta en performance sobre todo subscribirnos a tantos eventos y changesss no more changesss #lessonlearnt enter image description here

Otros metodos

Y sii los otros metodos involucran todo lo que dijimos antes :(

Metodo 2

@ViewChild de nuestro componente formulario hijo, algo como: (Viewchild link oficial)

    @ViewChild(ChildComponent) childComponent: ChildComponent;

Lo malo de esto es que por cada valor que cambia el control, subscribirnos al changes desde el hijo hacia el padre tiene que ser con algun emitter del valueChanges o algo similar. Hay muchos ejemplos de como se implementa pero… Neeeeext

Metodo 3 Control Value Accessor Link oficial

El famoso value accesorrrrr, lleno de ejemplos en todos lados y muchos metodos para poder implementarlo, con providers etc me parece muchisimo, si no es realmente necesario lo evitaria a toda costa :D

Espero esto les sirva y happy codinggggg!!!