13.11.2021 a las 10:25
Aprenderemos a cómo usar correctamente los formularios reactivos en Angular
Sin duda, los formularios reactivos de Angular me costaron al principio, me resistía a estudiarlos bien porque pensaba que algo tan fácil como un formulario no debía de tratarse de forma tan "compleja" como lo trataba Angular.
Mi error era pensar que Angular los trataba de una forma compleja, cuando en realidad lo que hace es facilitarnos el trabajo, tan sólo hay que dedicar unos minutos a comprenderlo.
Imagina que quieres crear la carta de un restaurante donde cada plato (menuItem) puede contener un número indeterminado de precios, como pueden ser:
Cada plato tendrá un nombre (name) que será obligatorio y como mínimo deberá tener 6 caracteres y por último, un array de objetos de precio que estará compuesto por una descripción (description) y un importe (price). El importe será obligatorio y tendrá un valor mínimo de 0.
{ "name":string, "prices":[ { description:string, price:number }, { description:string, price:number }, ... ] }
A continuación puedes ver lo que crearemos, un formulario que representará cada menuItem donde podremos añadir un número indeterminado de precios.
Como verás tengo asignado el CSS en el HTML. Sé que no es una buena práctica, pero como era poco CSS lo he preferido hacer así para no tener otro archivo para el CSS.
Para darle una mejor apariencia he usado Angular Material.
<form [formGroup]="formParent" style="border: grey 4px solid; padding: 1rem" > <p>Formulario válido: {{formParent.valid}}</p> <br> <div style="display: flex"> <mat-form-field appearance="outline" style="max-width: 200px"> <mat-label>Nombre</mat-label> <input type="text" autocomplete="off" matInput formControlName="name" /> <mat-icon matSuffix>description</mat-icon> <mat-error>Mínimo 6 caracteres</mat-error> </mat-form-field> <button class="mat-elevation-z4" type="button" mat-raised-button color="accent" (click)="addPrice()" style="height: 63.5px" > Añadir precio <mat-icon class="iconBtn">euro</mat-icon> </button> </div> <div formArrayName="prices"> <!-- fíjate que aquí no estamos asignando un formControlName, si no un formArrayName --> <div *ngFor=" let price of getCtrl('prices', formParent)?.controls; index as indexFormChildPrice " > <div [formGroupName]="indexFormChildPrice"> <mat-form-field appearance="outline" style="max-width: 200px"> <mat-label>Descripción</mat-label> <input type="text" autocomplete="off" matInput formControlName="description" /> <mat-icon matSuffix>description</mat-icon> </mat-form-field> <mat-form-field appearance="outline" style="width: 100px"> <mat-label>Precio</mat-label> <input type="number" autocomplete="off" matInput formControlName="price" /> <mat-icon matSuffix>dialpad</mat-icon> </mat-form-field> </div> </div> </div> </form>
import { Component, OnInit } from '@angular/core'; import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-angular-formularios-reactivos', templateUrl: './angular-formularios-reactivos.component.html', styles: [], }) export class AngularFormulariosReactivosComponent implements OnInit { public formParent: FormGroup = new FormGroup({}); //Creamos el formulario padre y lo inicializamos ngOnInit(): void { this.initFormParent(); } private initFormParent(): void { //crea el formulario padre y lo asigna a la variable formParent this.formParent = new FormGroup({ name: new FormControl('', [Validators.required, Validators.minLength(6)]), prices: new FormArray([], [Validators.required]), }); } private initFormPrice(): FormGroup { //devuelve un formulario hijo return new FormGroup({ description: new FormControl(''), price: new FormControl('', [Validators.required, Validators.min(0)]), }); } public addPrice(): void { //método que al pulsar en el botón de añadir precio añadirá un nueve elemento price al array prices const refPrices = <FormArray>this.formParent.get('prices'); refPrices.push(this.initFormPrice()); } public getCtrl(key: string, form: FormGroup) { return <FormArray>form.get(key); //con esto devolvemos la propiedad key del formulario form } }
Hasta luego 🖖
Software
IoT
Digitalización
Aplicaciones móviles
Consultoría