Reactive Forms

Overview

Angular Day - 16 Giugno 2017

Michele Stieven

Freelance Web Developer & JavaScript enthusiast

Obiettivi del talk

  • Reactive Form: il concetto

  • FormControl/FormGroup/FormArray

  • FormBuilder

  • Stato e manipolazione di un form

  • Validatori (built-in/custom)

  • Demo

@angular/forms

FormsModule

Template-driven forms

ReactiveFormsModule

Model-driven forms

import { ReactiveFormsModule } from "@angular/forms";

@NgModule({
    ...
    imports: [
        ReactiveFormsModule
    ]
})
...

Reactive Style

Spostamento della logica di un form dal template al controller.

  • #f="ngForm"

  • ngModel

  • required

  • ...

NO

Template-driven

<form #f="ngForm" (ngSubmit)="myMethod($event)">

        <input type="text"  
            [(ngModel)]="user.name" required>

        <input type="text"  
            [(ngModel)]="user.surname" required>

</form>

Model-driven

<form [formGroup]="user" (ngSubmit)="myMethod()">

        <input type="text" 
               formControlName="name">

        <input type="text" 
               formControlName="surname">

</form>

... Perché?

Validazioni

Pulizia

Controlli custom

Testing

Componenti principali

FormControl

singolo controllo (input, select, textarea...)

 

FormGroup

gruppo di controlli

 

FormArray

array di controlli

 

AbstractControl

classe generica

FormControl

name = new FormControl('Mario');
name = new FormControl({
    value: 'Mario',
    disabled: true
});

Oggetto

name = new FormControl(
    'Mario', 
    Validators.required
);

Validatore...

name = new FormControl(
    'Mario', 
    [
        Validators.required,
        Validators.minLength(4)
    ]
);

...o array di Validatori

FormGroup

myForm = new FormGroup({
  name: new FormControl('Mario'),
  surname: new FormControl('Rossi')
});

FormArray

cities = new FormArray([
  new FormControl('Verona'),
  new FormControl('Milano'),
  new FormControl('Roma')
]);

FormArray utilities

  • at

  • push

  • insert

  • removeAt

  • setControl

  • length

La classe ci mette a disposizione dei metodi per interagire con l'array:

AbstractControl

AbstractControl

  • value

  • parent

  • status

  • valid

  • invalid

  • pending

  • disabled

  • enabled

  • errors

Ogni controllo, estendendo questa classe, ci mette a disposizione queste proprietà:

Demo

FormGroup

FormControl

FormControl

FormArray

Custom Control

FormBuilder

FormBuilder è un servizio per semplificare la costruzione dei Reactive Form.

import { FormBuilder } from '@angular/forms';

@Component({
    ...
})
export class AppComponent {

    constructor(private fb: FormBuilder){ }

}
myForm = this.fb.group({
  name: 'Mario',
  surname: 'Rossi',
  phones: this.fb.array([])
});
myForm = new FormGroup({
  name: new FormControl('Mario'),
  surname: new FormControl('Rossi'),
  phones: new FormArray([])
});

Stati di un form/controllo

Dirty

Touched

Valid

Diventa true nel momento in cui l'utente clicca (focus) ed esce dal controllo (blur). Il suo opposto è untouched.

Diventa true nel momento in cui cambia il valore del controllo. Il suo opposto è pristine.

Diventa true se il controllo passa tutte le validazioni. Il suo opposto è invalid.

API Utilities

myForm.status

valid | invalid | pending | disabled

myForm.get('name')

myForm.controls.name

myForm.errors myForm.get('name').errors

{ ValidationErrors }

myForm.hasError('myError')

true | false

SetValue()

vs

PatchValue()

myForm = this.fb.group({
  name: '',
  surname: ''
});

setValue

patchValue

myForm.patchValue({
  name: 'Mario'
});
myForm.patchValue({
  name: 'Mario',
  surname: 'Rossi'
});
myForm.setValue({
  name: 'Mario'
});
myForm.setValue({
  name: 'Mario',
  surname: 'Rossi'
});
myForm.patchValue({
  name: 'Mario',
  surname: 'Rossi',
  age: 18
});
myForm.setValue({
  name: 'Mario',
  surname: 'Rossi',
  age: 18
});

myForm.reset()

  • Assegna il valore null ai controlli del form
  • Il form/controllo torna ad essere untouched e pristine
  • Possiamo resettare il form ad un valore specifico
  • Può essere applicato ai singoli controlli

Cosa fa:

Cosa non fa:

  • Non rimuove i controlli di un FormArray, li imposta a null

Validatori

Built-in validators

import { Validators } from '@angular/forms'

Validators.required

Validators.minLength()

Validators.maxLength()

Validators.pattern()

this.myForm = this.fb.group({
  name: ['', Validators.required],
  surname: ['', Validators.required],
  age: '18',
  phones: this.fb.array([])
});

Custom Validators

Un validatore custom è semplicemente una funzione!

 

Di tipo ValidatorFn

function customValidator(control: AbstractControl) {
    if (...) {
        return {Error: control.value}
    }
    return null;
};
function customValidator(myParams): ValidatorFn {
  return (control: AbstractControl) => {
    if (...) {
        // Do something with myParams
        return {Error: control.value}
    }
    return null;
  };
}

Validatore con parametri

export function nameValidator(param: string)
name: [
  '',
  [
    Validators.required,
    nameValidator('Michele')
  ]
]
import { AbstractControl, ValidatorFn } from '@angular/forms';

export function nameValidator(param): ValidatorFn {
  return (control: AbstractControl) => {
    if (control.value === param) {
        return {nameError: param}
    }
    return null;
  };
}

FormGroup Validators

Possiamo creare dei validatori custom per effettuare validazioni di più controlli all'interno di un FormGroup.

cred = {
    name: 'Mario',
    surname: 'Rossi'
};

[...]

this.myForm = this.fb.group({
  name: '',
  surname: ''
}, 
{ 
    validator: customCredentialsValidator(this.cred) 
});
export function customCredentialsValidator(cred) {
  return (control: AbstractControl) => {
    const name = control.get('name');
    const surname = control.get('surname');
    [...]
  };
};

...THE END?

Q&A

Ultima slide!

Ti è piaciuta la presentazione?

Ricorda di dare un voto al mio talk e all'Angular Day in generale!

Grazie!

Angular Dev Ita

JavaScript Dev Ita

Reactive Forms Overview

By Michele Stieven

Reactive Forms Overview

Angular Day 2017 - 16/06/2017

  • 240