SlideShare a Scribd company logo
1 of 36
Download to read offline
Custom Controls
In Angular Forms
Michele Stieven
Michele Stieven
Front-end Developer & Consultant
Obiettivi del talk
• Comprendere i vantaggi degli Angular Forms
• Creazione di un controllo custom
• Utilizzo dei controlli custom con Reactive e Template forms
• Capire come scrivere form annidati e riutilizzabili
• Vantaggi e svantaggi dell’approccio
Reactive Form Template-driven Form
• “Vivono” nella classe
• Facili da testare
• Facili da manipolare
• Facili da monitorare (RxJS!)
• Facili da validare
• Ideali per casi complessi
• Campi dinamici
• Validatori dinamici
• Interazioni con servizi
• …
• Facili da usare (in casi semplici)
• “Vivono” nel template
• Difficili da manipolare
• Difficili da testare
• Ideali per casi semplici
Angular Forms
Example
Template-driven Forms
<form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”>
<input type=“text” [(ngModel)]=“user.name” required>
<input type=“text” [(ngModel)]=“user.surname” required>
</form>
Creazione del Form
delegata ad Angular
Example
Template-driven Forms (one way binding)
<form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”>
<input type=“text” [ngModel]=“user.name” required>
<input type=“text” [ngModel]=“user.surname” required>
</form>
Creazione del Form
delegata ad Angular
Example
Template-driven Forms (no binding)
<form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”>
<input type=“text” ngModel required>
<input type=“text” ngModel required>
</form>
Creazione del Form
delegata ad Angular
Example
Reactive Forms
export class UserComponent {
public user = new FormGroup({
name: new FormControl(‘’, Validators.required),
surname: new FormControl(‘’, Validators.required)
})
}
Example
Reactive Forms
<form [formGroup]=“user” (ngSubmit)=“onSubmit()”>
<input type=“text” formControlName=“name”>
<input type=“text” formControlName=“surname”>
</form>
Creazione del Form nella
classe del componente
Architecture
Angular Forms
HTML Controls
Forms API
Directives
ngModel FormGroup
FormArray FormControl
User change Model change
Architecture
Angular Forms
HTML Controls
Forms API
Directives
ngModel FormGroup
FormArray FormControl
Value Accessors
Text Select
Radio Checkbox
ValueAccessor
• Come aggiornare l’elemento HTML
• Quando e come aggiornare il modello
Comunicazione fra @Directive e HTML
Value Accessors
<input type=“text”>
ngModel
Directive
Architecture
ValueAccessor predefiniti
DefaultValueAccessor
RadioControlValueAccessor
CheckboxControlValueAccessor
SelectControlValueAccessor
SelectMultipleControlValueAccessor
Input type=“text|textarea”
Input type=“radio”
Input type=“checkbox”
Select
Select multiple
ControlValueAccessor
Architecture
ControlValueAccessor Interface
writeValue(value: any): void
registerOnChange(fn: any): void
registerOnTouched(fn: any): void
setDisabledState(isDisabled: boolean)?: void
Il modello ha cambiato valore
Forniscono le funzioni per cambiare
il modello (valore, stato)
Il modello è stato disabilitato
Live code
Introducing ControlValueAccessor
Forms API @Component
Architecture
Cosa abbiamo ottenuto
RatingComponent
ngModel, formControlName…
RatingValueAccessor
Component change
Form change
ControlValueAccessor
Cosa abbiamo ottenuto
• Il componente continua a funzionare anche senza form
• Il componente comunica perfettamente con un form padre
• Riutilizzabile sia per Reactive che Template-driven forms!
• Best practice: basso rischio di errori
<options-images
formControlName=“front”
[options]=“images”
[type]=“‘round’”
[orientation]=“‘horizontal’”
</options-images>
ControlValueAccessor
Cosa possiamo ottenere
• Form nidificati
• Auto-validazione (attenzione!)
Example
Form Nidificati
<form>
<customer></customer>
<address></address>
<payment></payment>
</form>
nome, cognome, codice fiscale…
indirizzo, città, cap, nazione…
metodo, numero di carta…
Form nidificati
Bad Practice #1: passare il form al componente
<form #f=“NgForm”>
<customer [form]=“f”></customer>
<address [form]=“f”></address>
<payment [form]=“f”></payment>
</form>
Form nidificati
Bad Practice #1: passare il form al componente
<form [formGroup]=“form”>
<customer [form]=“form”></customer>
<address [form]=“form”></address>
<payment [form]=“form”></payment>
</form>
Form nidificati
Bad Practice #1: passare il form al componente
• Un sotto-componente manipola una nostra proprietà
• Può agganciarsi a controlli esistenti
• Può crearne di nuovi
• Può modificare il form e il suo stato
• Il form diventa fuori controllo
• Alto rischio di bug
Form nidificati - Reactive Forms
Bad Practice #2: accedere al form padre
constructor(parentForm: FormGroupDirective) {
parentForm.addControl(‘customer’, new FormGroup({
name: new FormControl(),
surname: new FormControl(),
fiscalCode: new FormControl()
}));
}
Form nidificati - Template-driven Forms
Bad Practice #2: accedere al form padre
@Component({
selector: ‘customer’,
template: ‘
<div ngModelGroup=“customer”>
<input ngModel name=“name”>
<input ngModel name=“surname”>
</div>
’,
viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]
})
Form nidificati
Bad Practice #2: accedere al form padre
• Un sotto-componente manipola una nostra proprietà
• Può agganciarsi a controlli esistenti
• Può crearne di nuovi
• Può modificare il form e il suo stato
• E noi non lo vediamo nemmeno! (no binding)
• Il form diventa fuori controllo
• Alto rischio di bug
• Non riutilizzabile fra Reactive e Template-driven forms
Form nidificati
Best Practice: ControlValueAccessor
<form [formGroup]=“form”>
<customer formControlName=“customer”></customer>
<address formControlName=“address”></address>
<payment formControlName=“payment”></payment>
</form>
Form nidificati
Best Practice: ControlValueAccessor
• Può contenere un form indipendente dal principale
• Incapsulato: non accede al padre direttamente
• Basso rischio di bug
• Riutilizzabile sia con Reactive che Template-driven forms
• Rimane un componente: possiamo passargli [input] e ricevere (output)
• Dà soddisfazione personale allo sviluppatore!
Form nidificati
Gestione degli errori
• Best practice: il validatore si applica dall’esterno (componente del form principale)
• Se ci pensate, un input non si valida da solo, è solamente un contenitore
• Potete usare sia funzioni validatrici (reactive) che direttive validatrici (template-driven)
• Se il componente deve visualizzare errori internamente, possiamo passarli come [input] oppure AL LIMITE iniettare
NgControl (attenzione)
• Il controllo può auto-validarsi implementando l’interfaccia Validator
• Massima attenzione: guardando il componente padre, non ve ne accorgerete
Form nidificati - Template-driven forms
Gestione degli errori: dall’esterno
<form #f=“NgForm”>
<customer ngModel customerValidator />
<address ngModel addressValidator />
<payment ngModel paymentValidator />
</form>
Form nidificati - Reactive forms
Gestione degli errori: dall’esterno
this.form = new FormGroup({
customer: new FormControl({}, customerValidator),
address: new FormControl({}, addressValidator),
payment: new FormControl({}, paymentValidator)
})
ControlValueAccessor
Gestione degli errori: auto-validazione
@Component({
…
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: MyComponent, multi: true },
{ provide: NG_VALIDATORS, useExisting: MyComponent, multi: true }
]
})
export class MyComponent implements ControlValueAccessor, Validator {
validate(control: AbstractControl) {
return { … } || null;
}
}
ControlValueAccessor
Gestione degli errori: auto-validazione async
@Component({
…
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: MyComponent, multi: true },
{ provide: NG_ASYNC_VALIDATORS, useExisting: MyComponent, multi: true }
]
})
export class MyComponent implements ControlValueAccessor, AsyncValidator {
validate(control: AbstractControl) {
return of({ … } || null);
}
}
Custom Controls
Riepilogo
• Creare controlli custom è facile grazie a ControlValueAccessor
• Riutilizzabili fra Reactive e Template-driven forms
• È la soluzione ideale per form annidati complessi
• Applicate i validatori dal padre, se possibile…
• …altrimenti utilizzate le interfacce Validator / AsyncValidator
• Evitate di iniettare controlli padre nei figli
• Evitate di consegnare il form ai componenti figli
Custom Controls in Angular Forms
Link utili
• Slide del talk:
• …
• Contatti:
• Facebook — https://fb.com/michelestieven
• Twitter — https://twitter.com/MicheleStieven
• Medium — https://medium.com/@michelestieven
• LinkedIn — https://linkedin.com/in/michelestieven
• Website — https://michelestieven.it

More Related Content

Similar to Custom Controls in Angular Forms

Slide typescript - net campus
Slide typescript - net campusSlide typescript - net campus
Slide typescript - net campus
DotNetCampus
 

Similar to Custom Controls in Angular Forms (20)

Gestione commesse (pm) NAV 2016
Gestione commesse (pm) NAV 2016Gestione commesse (pm) NAV 2016
Gestione commesse (pm) NAV 2016
 
Sviluppo Agile secondo l'approccio SCRUM
Sviluppo Agile secondo l'approccio SCRUMSviluppo Agile secondo l'approccio SCRUM
Sviluppo Agile secondo l'approccio SCRUM
 
PRICING - SLIDE CONVEGNO
PRICING - SLIDE CONVEGNOPRICING - SLIDE CONVEGNO
PRICING - SLIDE CONVEGNO
 
Laboratorio internet 10: Redazione dei contenuti
Laboratorio internet 10: Redazione dei contenutiLaboratorio internet 10: Redazione dei contenuti
Laboratorio internet 10: Redazione dei contenuti
 
Procedure per il lancio e mantenimento di un progetto Magento
Procedure per il lancio e mantenimento di un progetto MagentoProcedure per il lancio e mantenimento di un progetto Magento
Procedure per il lancio e mantenimento di un progetto Magento
 
Tecniche Di Troubleshooting Nei Sistemi Distribuiti
Tecniche Di Troubleshooting Nei Sistemi DistribuitiTecniche Di Troubleshooting Nei Sistemi Distribuiti
Tecniche Di Troubleshooting Nei Sistemi Distribuiti
 
ASP.NET MVC: sfruttare la piattaforma al 100%
ASP.NET MVC: sfruttare la piattaforma al 100%ASP.NET MVC: sfruttare la piattaforma al 100%
ASP.NET MVC: sfruttare la piattaforma al 100%
 
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
Manuel Toniato e Simone Caretta: Migliorare le performance di ricerca con Ela...
 
Iso 9001 2000 Sezione VII
Iso 9001 2000 Sezione VIIIso 9001 2000 Sezione VII
Iso 9001 2000 Sezione VII
 
SUE AGILE Framework (Italiano)
SUE AGILE Framework (Italiano)SUE AGILE Framework (Italiano)
SUE AGILE Framework (Italiano)
 
UserPie
UserPieUserPie
UserPie
 
AngularJS-Intro
AngularJS-IntroAngularJS-Intro
AngularJS-Intro
 
Migliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.jsMigliora il tuo codice con knockout.js
Migliora il tuo codice con knockout.js
 
Manuale gestione studi consulenza
Manuale gestione studi consulenzaManuale gestione studi consulenza
Manuale gestione studi consulenza
 
Manuale CRM Sicurweb
Manuale CRM SicurwebManuale CRM Sicurweb
Manuale CRM Sicurweb
 
Lean Management - ottobre 2014
Lean Management - ottobre 2014Lean Management - ottobre 2014
Lean Management - ottobre 2014
 
TYPESCRIPT, ANGULAR E BOOTSTRAP ASSIEME PER APPLICAZIONI REAL WORLD
TYPESCRIPT, ANGULAR E BOOTSTRAP ASSIEME PER APPLICAZIONI REAL WORLDTYPESCRIPT, ANGULAR E BOOTSTRAP ASSIEME PER APPLICAZIONI REAL WORLD
TYPESCRIPT, ANGULAR E BOOTSTRAP ASSIEME PER APPLICAZIONI REAL WORLD
 
Slide typescript - net campus
Slide typescript - net campusSlide typescript - net campus
Slide typescript - net campus
 
Slide webinar “Dalla fattura elettronica alla digitalizzazione del Ciclo Pass...
Slide webinar “Dalla fattura elettronica alla digitalizzazione del Ciclo Pass...Slide webinar “Dalla fattura elettronica alla digitalizzazione del Ciclo Pass...
Slide webinar “Dalla fattura elettronica alla digitalizzazione del Ciclo Pass...
 
Scientia 4.0 #elearning #training
Scientia 4.0 #elearning #trainingScientia 4.0 #elearning #training
Scientia 4.0 #elearning #training
 

Custom Controls in Angular Forms

  • 1. Custom Controls In Angular Forms Michele Stieven
  • 3. Obiettivi del talk • Comprendere i vantaggi degli Angular Forms • Creazione di un controllo custom • Utilizzo dei controlli custom con Reactive e Template forms • Capire come scrivere form annidati e riutilizzabili • Vantaggi e svantaggi dell’approccio
  • 4. Reactive Form Template-driven Form • “Vivono” nella classe • Facili da testare • Facili da manipolare • Facili da monitorare (RxJS!) • Facili da validare • Ideali per casi complessi • Campi dinamici • Validatori dinamici • Interazioni con servizi • … • Facili da usare (in casi semplici) • “Vivono” nel template • Difficili da manipolare • Difficili da testare • Ideali per casi semplici Angular Forms
  • 5. Example Template-driven Forms <form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”> <input type=“text” [(ngModel)]=“user.name” required> <input type=“text” [(ngModel)]=“user.surname” required> </form> Creazione del Form delegata ad Angular
  • 6. Example Template-driven Forms (one way binding) <form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”> <input type=“text” [ngModel]=“user.name” required> <input type=“text” [ngModel]=“user.surname” required> </form> Creazione del Form delegata ad Angular
  • 7. Example Template-driven Forms (no binding) <form #userForm=“NgForm” (ngSubmit)=“onSubmit(userForm)”> <input type=“text” ngModel required> <input type=“text” ngModel required> </form> Creazione del Form delegata ad Angular
  • 8. Example Reactive Forms export class UserComponent { public user = new FormGroup({ name: new FormControl(‘’, Validators.required), surname: new FormControl(‘’, Validators.required) }) }
  • 9. Example Reactive Forms <form [formGroup]=“user” (ngSubmit)=“onSubmit()”> <input type=“text” formControlName=“name”> <input type=“text” formControlName=“surname”> </form> Creazione del Form nella classe del componente
  • 10. Architecture Angular Forms HTML Controls Forms API Directives ngModel FormGroup FormArray FormControl User change Model change
  • 11. Architecture Angular Forms HTML Controls Forms API Directives ngModel FormGroup FormArray FormControl Value Accessors Text Select Radio Checkbox
  • 12. ValueAccessor • Come aggiornare l’elemento HTML • Quando e come aggiornare il modello Comunicazione fra @Directive e HTML Value Accessors <input type=“text”> ngModel Directive
  • 14. Architecture ControlValueAccessor Interface writeValue(value: any): void registerOnChange(fn: any): void registerOnTouched(fn: any): void setDisabledState(isDisabled: boolean)?: void Il modello ha cambiato valore Forniscono le funzioni per cambiare il modello (valore, stato) Il modello è stato disabilitato
  • 16. Architecture Cosa abbiamo ottenuto RatingComponent ngModel, formControlName… RatingValueAccessor Component change Form change
  • 17. ControlValueAccessor Cosa abbiamo ottenuto • Il componente continua a funzionare anche senza form • Il componente comunica perfettamente con un form padre • Riutilizzabile sia per Reactive che Template-driven forms! • Best practice: basso rischio di errori
  • 18.
  • 20. ControlValueAccessor Cosa possiamo ottenere • Form nidificati • Auto-validazione (attenzione!)
  • 21. Example Form Nidificati <form> <customer></customer> <address></address> <payment></payment> </form> nome, cognome, codice fiscale… indirizzo, città, cap, nazione… metodo, numero di carta…
  • 22. Form nidificati Bad Practice #1: passare il form al componente <form #f=“NgForm”> <customer [form]=“f”></customer> <address [form]=“f”></address> <payment [form]=“f”></payment> </form>
  • 23. Form nidificati Bad Practice #1: passare il form al componente <form [formGroup]=“form”> <customer [form]=“form”></customer> <address [form]=“form”></address> <payment [form]=“form”></payment> </form>
  • 24. Form nidificati Bad Practice #1: passare il form al componente • Un sotto-componente manipola una nostra proprietà • Può agganciarsi a controlli esistenti • Può crearne di nuovi • Può modificare il form e il suo stato • Il form diventa fuori controllo • Alto rischio di bug
  • 25. Form nidificati - Reactive Forms Bad Practice #2: accedere al form padre constructor(parentForm: FormGroupDirective) { parentForm.addControl(‘customer’, new FormGroup({ name: new FormControl(), surname: new FormControl(), fiscalCode: new FormControl() })); }
  • 26. Form nidificati - Template-driven Forms Bad Practice #2: accedere al form padre @Component({ selector: ‘customer’, template: ‘ <div ngModelGroup=“customer”> <input ngModel name=“name”> <input ngModel name=“surname”> </div> ’, viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] })
  • 27. Form nidificati Bad Practice #2: accedere al form padre • Un sotto-componente manipola una nostra proprietà • Può agganciarsi a controlli esistenti • Può crearne di nuovi • Può modificare il form e il suo stato • E noi non lo vediamo nemmeno! (no binding) • Il form diventa fuori controllo • Alto rischio di bug • Non riutilizzabile fra Reactive e Template-driven forms
  • 28. Form nidificati Best Practice: ControlValueAccessor <form [formGroup]=“form”> <customer formControlName=“customer”></customer> <address formControlName=“address”></address> <payment formControlName=“payment”></payment> </form>
  • 29. Form nidificati Best Practice: ControlValueAccessor • Può contenere un form indipendente dal principale • Incapsulato: non accede al padre direttamente • Basso rischio di bug • Riutilizzabile sia con Reactive che Template-driven forms • Rimane un componente: possiamo passargli [input] e ricevere (output) • Dà soddisfazione personale allo sviluppatore!
  • 30. Form nidificati Gestione degli errori • Best practice: il validatore si applica dall’esterno (componente del form principale) • Se ci pensate, un input non si valida da solo, è solamente un contenitore • Potete usare sia funzioni validatrici (reactive) che direttive validatrici (template-driven) • Se il componente deve visualizzare errori internamente, possiamo passarli come [input] oppure AL LIMITE iniettare NgControl (attenzione) • Il controllo può auto-validarsi implementando l’interfaccia Validator • Massima attenzione: guardando il componente padre, non ve ne accorgerete
  • 31. Form nidificati - Template-driven forms Gestione degli errori: dall’esterno <form #f=“NgForm”> <customer ngModel customerValidator /> <address ngModel addressValidator /> <payment ngModel paymentValidator /> </form>
  • 32. Form nidificati - Reactive forms Gestione degli errori: dall’esterno this.form = new FormGroup({ customer: new FormControl({}, customerValidator), address: new FormControl({}, addressValidator), payment: new FormControl({}, paymentValidator) })
  • 33. ControlValueAccessor Gestione degli errori: auto-validazione @Component({ … providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: MyComponent, multi: true }, { provide: NG_VALIDATORS, useExisting: MyComponent, multi: true } ] }) export class MyComponent implements ControlValueAccessor, Validator { validate(control: AbstractControl) { return { … } || null; } }
  • 34. ControlValueAccessor Gestione degli errori: auto-validazione async @Component({ … providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: MyComponent, multi: true }, { provide: NG_ASYNC_VALIDATORS, useExisting: MyComponent, multi: true } ] }) export class MyComponent implements ControlValueAccessor, AsyncValidator { validate(control: AbstractControl) { return of({ … } || null); } }
  • 35. Custom Controls Riepilogo • Creare controlli custom è facile grazie a ControlValueAccessor • Riutilizzabili fra Reactive e Template-driven forms • È la soluzione ideale per form annidati complessi • Applicate i validatori dal padre, se possibile… • …altrimenti utilizzate le interfacce Validator / AsyncValidator • Evitate di iniettare controlli padre nei figli • Evitate di consegnare il form ai componenti figli
  • 36. Custom Controls in Angular Forms Link utili • Slide del talk: • … • Contatti: • Facebook — https://fb.com/michelestieven • Twitter — https://twitter.com/MicheleStieven • Medium — https://medium.com/@michelestieven • LinkedIn — https://linkedin.com/in/michelestieven • Website — https://michelestieven.it