Advertisement
  1. Code
  2. Angular

Introduzione ai form in Angular 4: i form Template-Driven

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Introduction to Forms in Angular 4.
Introduction to Forms in Angular 4: Reactive Forms

Italian (Italiano) translation by Cinzia Sgariglia (you can also view the original English article)

Final product image
What You'll Be Creating

I form sono fondamentali per qualsiasi applicazione moderna front-end, e sono un elemento che usiamo ogni giorno, anche se non lo sappiamo. I form sono necessari per far accedere in modo sicuro un utente all'app, per la ricerca di tutti gli hotel disponibili in una determinata città, per prenotare un taxi, per costruire una lista di cose da fare e fare tonnellate di altre cose a cui siamo abituati. Alcuni form hanno solo un paio di campi di input, mentre altri form potrebbero avere una matrice di campi che si estendono per un paio di pagine o schede.

In questo tutorial, parleremo di diverse strategie disponibili per lo sviluppo di form in Angular. Qualunque sia la strategia che scegliete, ecco le cose che una libreria di form dovrebbe coprire:

  • Supportare il legame bidirezionale in modo che i valori del controllo di input sono sincronizzati con lo stato del componente.
  • Tenere traccia dello stato del form e utilizzare segnali visivi per consentire all'utente di sapere se lo stato corrente è valido o no. Per esempio, se il nome utente contiene caratteri non validi, dovrebbe apparire un bordo rosso intorno al campo di input del nome utente.
  • Avere un meccanismo per visualizzare correttamente gli errori di convalida.
  • Abilitare o disabilitare determinate parti del form, a meno che non sono soddisfatti alcuni criteri di convalida.

Introduzione ai form in Angular

Angular, essendo un vero e proprio framework front-end, ha un proprio set di librerie per la creazione di form complessi. L'ultima versione di Angular ha due potenti strategie per la costruzione del form. Sono:

  • i form template driven
  • i form model driven o reactive

Entrambe le tecnologie appartengono alla libreria @angular/forms e sono basate sulle stesse classi di controllo del form. Tuttavia, essi differiscono notevolmente nella loro filosofia, stile di programmazione e tecnica. Scegliere uno rispetto all'altro dipende dal vostro gusto personale e anche dalla complessità del form che state tentando di creare. A mio parere, dovreste provare entrambi gli approcci prima e poi scegliere uno che si adatta al vostro stile e al progetto sottomano.

La prima parte del tutorial coprirà i form template-driven con un esempio pratico: la costruzione di un modulo di iscrizione con convalida per tutti i campi del modulo. Nella seconda parte di questo tutorial, ripercorreremo i passaggi per creare lo stesso form utilizzando invece un approccio model-driven.

I form Template-Driven

L'approccio basato sul template-driven è una strategia che è stato preso in prestito dall'epoca di AngularJS. A mio parere, è il metodo più semplice per la creazione di form. Come funziona? Useremo alcune direttive di Angular.

Le direttive vi consentono di collegare il comportamento agli elementi nel DOM.
Documentazione di Angular

Angular fornisce direttive specifiche per i form che è possibile utilizzare per associare i dati di input del modulo e il modello. Le direttive specifiche per i form aggiungono funzionalità extra e comportamento a un semplice form HTML. Il risultato finale è che il modello si occupa dei valori collegati con la convalida del modello e del form.

In questo tutorial, useremo il form template-driven per creare la pagina di iscrizione a un'applicazione. Il modulo coprirà gli elementi più comuni dei form e diversi controlli di convalida su questi elementi del form. Qui ci sono i passi che si seguiranno in questo tutorial.

  • Aggiungere FormsModule a app.module.ts.
  • Creare una classe per il modello utente.
  • Creare i componenti iniziali e il layout per il modulo di iscrizione.
  • Usare le direttive di Angular per i form come ngModel, ngModelGroup e ngForm.
  • Aggiungere la convalida utilizzando i validatori integrati.
  • Visualizzare significativamente gli errori di convalida.
  • Gestire l'invio di moduli utilizzando ngSubmit.

Iniziamo.

Prerequisiti

Il codice per questo progetto è disponibile sul mio repo di GitHub. Scaricate lo zip o clonate il repo per vederlo in azione. Se si preferisce iniziare da zero invece, assicuratevi di aver installato Angular CLI. Utilizzate il comando ng per generare un nuovo progetto.

Successivamente, generate un nuovo componente per il SignupForm.

Sostituite il contenuto di app.component.html con questo:

Ecco la struttura della directory per la directory src /. Ho rimosso alcuni file non essenziali per mantenere le cose semplici.

Come potete vedere, è stata creata automaticamente una directory per il componente SignupForm. Che è dove andrà la maggior parte del nostro codice. Ho anche creato un nuovo User.ts per memorizzare il nostro modello utente.

Il template HTML

Prima di tuffarci nel template del componente, abbiamo bisogno di avere un'idea astratta di quello che stiamo costruendo. Così ecco la struttura del form che ho nella mia mente. Il modulo di iscrizione avrà diversi campi di input, un elemento select e un elemento checkbox.

The HTML Template

Ecco il modello HTML che useremo per la nostra pagina di iscrizione.

Template HTML

Le classi CSS utilizzate nel modello HTML sono parte della libreria Bootstrap utilizzata per fare cose carine. Poiché questa non è un un'esercitazione di disegno, non parlerò molto degli aspetti CSS del modulo a meno che non sia necessario.

Installazione del form di base

Per utilizzare le direttive del form template-driven, abbiamo bisogno di importare FormsModule da @angular/forms e aggiungerlo nella matrice import in app.module.ts.

app/app.module.ts

Successivamente, creare una classe che conterrà tutte le proprietà dell'entità utente. Noi possiamo utilizzare un'interfaccia e implementarla nel componente oppure utilizzare una classe dattiloscritto per il modello.

app/User.ts

Ora, creare un'istanza della classe del componente SignupForm. Ho anche dichiarato una proprietà aggiuntiva per il genere.

app/signup-form/signup-form.component.ts

Per il file di signup-form.component.html, ho intenzione di utilizzare lo stesso modello HTML discusso sopra, ma con modifiche minori. Il modulo di iscrizione ha un campo selezionato con un elenco di opzioni. Anche se funziona, lo faremo al modo di Angular scorrendo l'elenco tramite la direttiva ngFor.

app/signup-form/signup-form.component.html

Poi, vogliamo associare i dati del form all'oggetto della classe utente, in modo che quando immettete i dati registrati nel modulo, viene creato un nuovo oggetto utente che archivia temporaneamente i dati. In questo modo, potete mantenere la vista sincronizzata con il modello, e questa operazione è detta binding.

Ci sono un paio di modi per far sì che questo accada. Permettetemi di introdurvi prima ngModel e ngForm.

ngForm e ngModel

ngForm e ngModel sono direttive di Angular che sono essenziali per creare form template-driven. Iniziamo prima con ngForm. Ecco un estratto su ngForm dalla documentazione di Angular.

La direttiva NgForm integra l'elemento form con funzionalità aggiuntive. Essa detiene i controlli creati per gli elementi con una direttiva ngModel e attributo name e monitora le loro proprietà, inclusa la loro validità. Ha anche una propria proprietà valid che restituisce true solo se ogni controllo contenuto è valido.

In primo luogo, aggiornate il modulo con la direttiva ngForm:

app/signup-form/signup-form.component.html

#signupForm è una variabile di riferimento del template che fa riferimento alla direttiva ngForm che governa l'intero modulo. Nell'esempio seguente viene illustrato l'utilizzo di un oggetto di riferimento ngForm per la convalida.

app/signup-form/signup-form.component.html

Qui, signupForm.form.valid restituirà false a meno che tutti gli elementi del modulo passano i rispettivi controlli di convalida. Il pulsante di invio verrà disattivato fino a quando il modulo è valido.

Per quanto riguarda il binding del template e del modello, ci sono un sacco di modi per fare questo, e ngModel ha tre diverse sintassi per affrontare questa situazione. Sono:

  1. [(ngModel)]
  2. [ngModel]
  3. ngModel

Cominciamo con il primo.

Il binding bidirezionale usando [(ngModel)]

[(ngModel)] esegue il binding bidirezionale per la lettura e la scrittura di valori di controllo di input. Se viene utilizzata una direttiva [(ngModel)], il campo di input prende un valore iniziale dalla classe componente associata e lo aggiorna ogni volta che qualsiasi modifica del valore di controllo dell'input viene rilevato (azionando un tasto e premendo un pulsante). L'immagine qui sotto descrive meglio il processo di binding bidirezionale.

Two-way binding with ngModel

Ecco il codice per il campo di input e-mail:

[(ngModel)] = "user.email" collega la proprietà email dell'utente al valore di input. Ho anche aggiunto un attributo name e impostato name = "email". Questo è importante, e otterrete un errore se non avete dichiarato un attributo name durante l'utilizzo di ngModel.

Allo stesso modo, aggiungete un [(ngModel)] e un attributo name univoco a ogni elemento del form. Il vostro modulo dovrebbe essere simile a questo ora:

app/signup-form/signup-form.component.html

ngModelGroup viene utilizzato per raggruppare i campi di modulo simili, in modo che possiamo eseguire le convalide solo su quei campi del modulo. Dal momento che entrambi i campi password sono legati, li metteremo sotto un singolo ngModelGroup. Se tutto funziona come previsto, la proprietà del componente associato user dovrebbe essere responsabile della memorizzazione di tutti i valori di controllo del modulo. Per vederla in azione, è necessario aggiungere la seguente dopo il tag form:

Reindirizzate la proprietà utente attraverso JsonPipe per eseguire il rendering del modello come JSON nel browser. Questo è utile per il debug e l'autenticazione. Si dovrebbe vedere un output JSON come questo.

An example of JSON output

I valori stanno fluendo dalla vista al modello. E riguardo all'altro modo? Provate a inizializzare l'oggetto utente con alcuni valori.

app/signup-form/signup-form.component.ts

E automaticamente appaiono nella vista:

La sintassi di binding bidirezionale [(ngModel)] consente di compilare moduli senza sforzo. Tuttavia, ha alcuni inconvenienti; quindi, c'è un approccio alternativo che utilizza ngModel o [ngModel].

Aggiungere ngModel al mix

Quando ngModel viene utilizzato, in realtà siamo responsabili dell'aggiornamento della proprietà del componente con i valori del controllo di input e viceversa. I dati di input non scorrono automaticamente nella proprietà utente del componente.

Così sostituite tutte le istanze di [(ngModel)] = " " con ngModel. Manterremo l'attributo name perché tutte e tre le versioni di ngModel hanno bisogno dell'attributo name per funzionare.

app/signup-form/signup-form.component.html

Con ngModel, il valore dell'attributo name diventerà una chiave dell'oggetto di riferimento di ngForm, signupForm, che abbiamo creato in precedenza. Così, ad esempio, signupForm.value.email memorizzerà il valore di controllo per l'id della posta elettronica.

Sostituite {{user | json}} con {{signupForm.value | json}} perché è dove tutti gli state sono archiviati in questo momento.

Il binding unidirezionale usando [ngModel]

E se avete bisogno di impostare lo stato iniziale del componente associato della classe? Ecco cosa fa per voi [ngModel].

One-way binding with ngModel

Qui i dati passano dal modello alla vista. Apportate le seguenti modifiche alla sintassi per utilizzare il binding unidirezionale:

app/signup-form/signup-form.component.html

Così quale approccio scegliereste? Se state usando [(ngModel)] e ngForm insieme, alla fine avrete due stati da mantenere — user e signupForm.value — e potrebbe essere una potenziale fonte di confusione.

Quindi, consiglierei di utilizzare invece il metodo di binding unidirezionale. Ma questo sta a voi deciderlo.

Convalida e visualizzazione dei messaggi di errore

Ecco i nostri requisiti per la convalida.

  • Tutti i controlli del form sono obbligatori.
  • Disattivare il pulsante di invio fino a quando tutti i campi di input sono pieni.
  • Il campo email deve contenere rigorosamente un id di posta elettronica.
  • Il campo password deve avere una lunghezza minima di 8.
  • La password e la conferma devono corrispondere.
Form with Validation using Template-driven forms
Il nostro form con convalida operativa

Il primo è facile. È necessario aggiungere un attributo di convalida required per ogni elemento del form come questo:

app/signup-form/signup-form.component.html

A parte l'attributo required, ho esportato anche una nuova variabile di riferimento del modello #email. Questo è solo per farvi accedere alla casella input di controllo di Angular dall'interno del modello stesso. La useremo per visualizzare errori e avvisi. Ora è possibile utilizzare la proprietà del pulsante disabilitata per disattivare il pulsante:

app/signup-form/signup-form.component.html

Per aggiungere un vincolo sull'e-mail, utilizzate l'attributo pattern che funziona con i campi di input. I pattern vengono utilizzati per specificare le espressioni regolari come quella riportata di seguito:

Per il campo della password, tutto quello che dovrete fare è aggiungere un attributo minlength = " ":

app/signup-form/signup-form.component.html

Per visualizzare gli errori, ho intenzione di utilizzare la  direttiva condizionale ngIf su un elemento div. Iniziamo con il campo di controllo di input per l'e-mail:

app/signup-form/signup-form.component.html

C'è molto da fare qui. Cominciamo con la prima riga della sezione di errore.

Ricordate la variabile #email che abbiamo esportato in precedenza? Trasporta una quantità di informazioni sullo stato di controllo dell'input del campo email. Questo include: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched ed email.errors. L'immagine qui sotto descrive tali proprietà in dettaglio.

Different class properties for displaying errors

Così l'elemento div con il *ngIf verrà visualizzato solo se l'email non è valida. Tuttavia, l'utente sarà accolto con errori sui campi di input vuoti ancor prima che abbiano la possibilità di modificare il modulo.

Per evitare questo scenario, abbiamo aggiunto la seconda condizione. Verrà visualizzato l'errore solo dopo che il controllo è stato visitato o il valore del controllo è stato modificato.

Gli elementi div annidati vengono utilizzati per coprire tutti i casi di errori di convalida. Usiamo email.errors per controllare tutti i possibili errori di convalida e quindi di visualizzarli all'utente sotto forma di messaggi personalizzati. Ora, seguiamo la stessa procedura per gli altri elementi del modulo. Ecco come ho codificato la convalida per le password.

app/signup-form/signup-form.component.html

Questo sta cominciando a sembrare un po' disordinato. Angular ha un insieme limitato di attributi di convalida: required, pattern, maxlength e minlength. Per coprire qualsiasi altro scenario come quello del confronto delle password, dovrete fare affidamento su istruzioni condizionali annidate ngIf come ho fatto sopra. O in teoria, creare una funzione di convalida personalizzata, che viene descritta nella terza parte di questa serie.

Nel codice sopra, ho usato la sintassi ngIf else introdotta con l'ultima versione di Angular. Ecco come funziona:

Inviare il modulo tramite ngSubmit

Abbiamo quasi finito il modulo. Ora abbiamo bisogno di essere in grado di inviare il modulo, e il controllo dei dati del modulo dovrebbe essere affidato a un metodo componente, diciamo onFormSubmit().

app/signup-form/signup-form.component.ts

Ora, per il componente:

app/signup-form/signup-form.component.ts

Demo finale

Ecco la versione finale dell'applicazione. Ho aggiunto alcune classi bootstrap per rendere il form carino.

Riepilogo

Abbiamo finito qui. In questo tutorial, abbiamo coperto tutto quello che dovete sapere sulla creazione di un modulo in Angular utilizzando l'approccio template-driven. I form template-driven sono popolari per la loro semplicità e facilità d'uso.

Tuttavia, se avete bisogno di compilare un form con un sacco di elementi form, questo approccio diventerà disordinato. Così, nel prossimo tutorial, tratteremo il modo model-driven di creazione dello stesso modulo.

Condividete i vostri pensieri nei commenti qui sotto.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.