I moduli sono fondamentali per qualsiasi applicazione front-end moderna e sono una funzionalità che utilizziamo ogni giorno, anche se non ce ne rendiamo conto. I moduli sono necessari per accedere in sicurezza a un utente all'app, per cercare tutti gli hotel disponibili in una determinata città, prenotare un taxi, creare una lista di cose da fare e fare un sacco di altre cose a cui siamo abituati. Alcune forme hanno solo un paio di campi di input, mentre altri moduli potrebbero avere una matrice di campi che si estendono fino a un paio di pagine o schede.
In questo tutorial parleremo delle diverse strategie disponibili per lo sviluppo di forme in Angular. Indipendentemente dalla strategia scelta, ecco le cose che una biblioteca di moduli dovrebbe coprire:
Angolare, essendo un vero e proprio framework di front-end, ha il proprio set di librerie per la costruzione di forme complesse. L'ultima versione di Angular ha due potenti strategie di creazione di forme. Loro sono:
Entrambe le tecnologie appartengono al @ angolari / forme
libreria e si basano sulle stesse classi di controllo dei moduli. Tuttavia, differiscono notevolmente nella loro filosofia, nello stile di programmazione e nella tecnica. La scelta dell'uno sull'altro dipende dal tuo gusto personale e anche dalla complessità del modulo che stai cercando di creare. Secondo me, dovresti prima provare entrambi gli approcci e poi sceglierne uno che si adatti al tuo stile e al progetto in questione.
La prima parte del tutorial riguarderà i moduli basati su modelli con un esempio pratico: creazione di un modulo di registrazione con convalida per tutti i campi modulo. Nella seconda parte di questo tutorial, ripercorreremo i passaggi per creare la stessa forma utilizzando invece un approccio guidato dal modello.
L'approccio basato su modelli è una strategia presa in prestito dall'era AngularJS. Secondo me, è il metodo più semplice per costruire forme. Come funziona? Useremo alcune direttive angolari.
Le direttive consentono di collegare il comportamento agli elementi nel DOM.
- Documentazione angolare
Angular fornisce direttive specifiche per modulo che è possibile utilizzare per associare i dati di input del modulo e il modello. Le direttive specifiche del modulo aggiungono funzionalità e comportamenti extra a un semplice modulo HTML. Il risultato finale è che il modello si occupa dei valori di associazione con il modello e la convalida del modulo.
In questo tutorial, utilizzeremo moduli basati su modelli per creare la pagina di registrazione di un'applicazione. Il modulo coprirà gli elementi del modulo più comuni e diversi controlli di convalida su questi elementi del modulo. Ecco i passaggi che seguirai in questo tutorial.
app.module.ts
.ngModel
, ngModelGroup
, e ngForm
.ngSubmit
.Iniziamo.
Il codice per questo progetto è disponibile sul mio repository GitHub. Scarica il file zip o clona il repository per vederlo in azione. Se preferisci ripartire da zero, assicurati di aver installato la CLI Angolare. Utilizzare il ng
comando per generare un nuovo progetto.
$ ng nuovo SignupFormProject
Quindi, generare un nuovo componente per il SignupForm.
ng genera il componente SignupForm
Sostituisci il contenuto di app.component.html con questo:
Ecco la struttura della directory per src / directory. Ho rimosso alcuni file non essenziali per semplificare le cose.
. ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── modulo di iscrizione │ │ ├ ── signup-form.component.css │ │ ├── signup-form.component.html │ │ └── signup-form.component.ts │ └── User.ts ├── index.html ├── main .ts ├── polyfills.ts ├── styles.css ├── tsconfig.app.json └── typings.d.ts
Come puoi vedere, una directory per il SignupForm
componente è stato creato automaticamente. Ecco dove andrà la maggior parte del nostro codice. Ho anche creato un nuovo User.ts
per memorizzare il nostro modello utente.
Prima di immergerci nel modello di componente reale, abbiamo bisogno di avere un'idea astratta di ciò che stiamo costruendo. Quindi ecco la struttura del modulo che ho nella mia mente. Il modulo di iscrizione avrà diversi campi di input, un elemento select e un elemento checkbox.
Ecco il modello HTML che utilizzeremo per la nostra pagina di registrazione.
Le classi CSS utilizzate nel modello HTML fanno parte della libreria Bootstrap utilizzata per rendere le cose carine. Poiché non si tratta di un tutorial di progettazione, non parlerò molto degli aspetti CSS del modulo, a meno che non sia necessario.
Per utilizzare le direttive del modulo basato su modelli, è necessario importare il file FormsModule
a partire dal @ angolari / forme
e aggiungilo al importazioni
array in app.module.ts
.
import FormsModule da '@ angular / forms'; @NgModule (... imports: [BrowserModule, FormsModule], ...) Esporta classe AppModule
Quindi, crea una classe che includerà tutte le proprietà dell'entità Utente. Possiamo utilizzare un'interfaccia e implementarla nel componente o utilizzare una classe TypeScript per il modello.
classe di esportazione Utente id: numero; email: string; // Entrambe le password sono in una password per un singolo oggetto: pwd: string; confirmPwd: string; ; genere: stringa; termini: booleano; costruttore (valori: Object = ) // Inizializzazione costruttore Object.assign (this, values);
Ora, crea un'istanza della classe nel componente SignupForm. Ho anche dichiarato una proprietà aggiuntiva per il genere.
import Component, OnInit da '@ angular / core'; // Importa l'importazione del modello utente Utente da './... / Utente'; @Component (selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css']) classe di esportazione SignupFormComponent implementa OnInit // Proprietà per genere: genere privato: stringa []; // Proprietà per l'utente privato dell'utente: Utente; ngOnInit () this.gender = ['Male', 'Female', 'Others']; // Crea un nuovo oggetto utente this.user = new User (email: "", password: pwd: "", confirm_pwd: "", gender: this.gender [0], terms: false);
Per il iscrizione-form.component.html file, ho intenzione di utilizzare lo stesso modello HTML discusso sopra, ma con modifiche minori. Il modulo di iscrizione ha un campo di selezione con un elenco di opzioni. Anche se funziona, lo faremo in modo angolare scorrendo la lista usando il comando ngFor
direttiva.
Successivamente, vogliamo associare i dati del modulo all'oggetto classe utente in modo che quando si inseriscono i dati di registrazione nel modulo, venga creato un nuovo oggetto Utente che memorizza temporaneamente tali dati. In questo modo, puoi mantenere la vista in sincronia con il modello, e questo è chiamato binding.
Ci sono un paio di modi per farlo accadere. Lascia che prima ti presenti ngModel
e ngForm
.
ngForm e ngModel sono direttive angolari essenziali per la creazione di moduli basati su modelli. Iniziamo con ngForm
primo. Ecco un estratto su ngForm dai documenti Angular.
IlNgForm
direttiva integra ilmodulo
elemento con funzionalità aggiuntive. Contiene i controlli creati per gli elementi conngModel
direttiva enome
attributo e controlla le loro proprietà, compresa la loro validità. Ha anche il suovalido
proprietà che è vera solo se ogni controllo contenuto è valido.
Innanzitutto, aggiorna il modulo con ngForm
direttiva:
#signupForm
è una variabile di riferimento del modello che si riferisce al ngForm
direttiva che regola l'intera forma. L'esempio seguente dimostra l'uso di a ngForm
oggetto di riferimento per la convalida.
Qui, signupForm.form.valid
restituirà false a meno che tutti gli elementi del modulo non superino i rispettivi controlli di convalida. Il pulsante di invio sarà disabilitato finché il modulo non sarà valido.
Per quanto riguarda il binding del modello e del modello, ci sono molti modi per farlo, e ngModel
ha tre diverse sintassi per affrontare questa situazione. Loro sono:
Iniziamo con il primo.
[(NgModel)]
esegue il binding a due vie per leggere e scrivere valori di controllo di input. Se una [(NgModel)]
viene utilizzata la direttiva, il campo di input prende un valore iniziale dalla classe di componente associata e lo aggiorna nuovamente ogni volta che viene rilevata qualsiasi modifica al valore di controllo di input (sulla pressione di un tasto e del pulsante). L'immagine seguente descrive meglio il processo di associazione a due vie.
Ecco il codice per il campo di input dell'email:
[(ngModel)] = "user.email"
associa la proprietà email dell'utente al valore di input. Ho anche aggiunto un nome attributo e set name = "email"
. Questo è importante e riceverai un errore se non hai dichiarato un attributo name durante l'utilizzo di ngModel.
Allo stesso modo, aggiungi un [(NgModel)]
e un unico nome attributo a ciascun elemento del modulo. Il tuo modulo dovrebbe essere simile a questo ora:
......
Il ngModelGroup
viene utilizzato per raggruppare campi di moduli simili in modo che possiamo eseguire convalide solo su quei campi modulo. Poiché entrambi i campi della password sono correlati, li inseriremo in un singolo ngModelGroup. Se tutto funziona come previsto, il componente-bound utente
la proprietà dovrebbe essere responsabile di memorizzare tutti i valori di controllo del modulo. Per vedere questo in azione, aggiungi quanto segue dopo il tag del modulo:
utente | JSON
Conduci la proprietà dell'utente attraverso il JsonPipe
per rendere il modello come JSON nel browser. Questo è utile per il debug e la registrazione. Dovresti vedere un output JSON come questo.
I valori stanno entrando dalla vista al modello. E il contrario? Prova a inizializzare l'oggetto utente con alcuni valori.
this.user = new User (// inizializzato con alcuni dati email: "[email protected]", password: pwd: "", confirm_pwd: "", gender: this.gender [0]);
E compaiono automaticamente nella vista:
"email": "[email protected]", "password": "pwd": "", "confirm_pwd": "", "gender": "Male"
La rilegatura a doppio senso [(NgModel)]
la sintassi ti aiuta a costruire le forme senza sforzo. Tuttavia, ha alcuni inconvenienti; quindi, vi è un approccio alternativo che utilizza ngModel
o [NgModel]
.
quando ngModel
viene utilizzato, siamo infatti responsabili dell'aggiornamento della proprietà del componente con i valori di controllo di input e viceversa. I dati di input non fluiscono automaticamente nella proprietà utente del componente.
Quindi sostituire tutte le istanze di [(ngModel)] = ""
con ngModel
. Terremo il nome
attributo perché tutte e tre le versioni di ngModel hanno bisogno del nome
attributo a funzionare.
Con ngModel
, il valore dell'attributo name diventerà una chiave dell'oggetto di riferimento ngForm signupForm
che abbiamo creato in precedenza. Quindi, per esempio, signupForm.value.email
memorizzerà il valore di controllo per l'ID e-mail.
Sostituire utente | JSON
con signupForm.value | json
perché è lì che tutto lo stato è memorizzato in questo momento.
Cosa succede se è necessario impostare lo stato iniziale dal componente di classe associato? Questo è ciò che [NgModel]
fa per te.
Qui i dati passano dal modello alla vista. Apporta le seguenti modifiche alla sintassi per utilizzare l'associazione unidirezionale:
Quindi quale approccio dovresti scegliere? Se stai usando [(NgModel)]
e ngForm
insieme, alla fine avrai due stati da mantenere-utente
e signupForm.value
-e questo potrebbe essere potenzialmente confuso.
"email": "[email protected]", "password": "pwd": "thisispassword", "confirm_pwd": "thisispassword", "gender": "Male" //user.value " email ":" [email protected] "," password ": " pwd ":" thisispassword "," confirm_pwd ":" thisispassword "," gender ":" Male " //signupForm.value
Quindi, raccomanderò invece di usare il metodo di associazione unidirezionale. Ma è qualcosa che devi decidere.
Ecco i nostri requisiti per la convalida.
Il primo è facile. Devi aggiungere un necessario
attributo di convalida per ogni elemento del modulo come questo:
Oltre al necessario
attributo, ne ho esportato anche uno nuovo #e-mail
variabile di riferimento del modello. In questo modo è possibile accedere al controllo angolare della casella di input all'interno del modello stesso. Lo useremo per visualizzare errori e avvertenze. Ora usa la proprietà disabilitata del pulsante per disabilitare il pulsante:
Per aggiungere un vincolo all'e-mail, utilizzare l'attributo pattern che funziona con i campi di input. I pattern sono usati per specificare espressioni regolari come quella seguente:
modello = "[a-z0-9 ._% + -]. + @ [a-z0-9 .-] + \ [a-z] 2,3 $"
Per il campo della password, tutto ciò che devi fare è aggiungere un minlength = ""
attributo:
Per visualizzare gli errori, userò la direttiva condizionale ngIf
su un elemento div. Iniziamo con il campo di controllo di input per email:
Il campo email non può essere vuotoL'e-mail id non sembra giusta
C'è molto da fare qui. Iniziamo con la prima riga della sezione errori.
Ricorda il
email.valid
,email.invalid
,email.dirty
,email.pristine
,email.touched
,email.untouched
, eemail.errors
. L'immagine sotto descrive ciascuna di queste proprietà in dettaglio.Quindi l'elemento div con il
* ngIf
sarà reso solo se l'email non è valida. Tuttavia, l'utente verrà salutato con errori sui campi di input che sono vuoti anche prima che abbiano la possibilità di modificare il modulo.Per evitare questo scenario, abbiamo aggiunto la seconda condizione. L'errore verrà visualizzato solo dopo il controllo è stato visitato o il valore del controllo è stato modificato.
Gli elementi div nidificati vengono utilizzati per coprire tutti i casi di errori di convalida. Noi usiamo
email.errors
per verificare tutti gli errori di convalida possibili e quindi visualizzarli all'utente sotto forma di messaggi personalizzati. Ora, segui la stessa procedura per gli altri elementi del modulo. Ecco come ho codificato la convalida delle password.app / iscrizione-forma / iscrizione-form.component.html
La password deve contenere più di 8 caratteriLe password non corrispondono Questo sta iniziando a sembrare un po 'disordinato. Angolare ha un set limitato di attributi del validatore:
necessario
,minlength
,lunghezza massima
, emodello
. Per coprire qualsiasi altro scenario come quello del confronto delle password, dovrai fare affidamento su nidificatongIf
condizionali come ho fatto sopra. O idealmente, crea una funzione di validatore personalizzato, che tratterò nella terza parte di questa serie.Nel codice sopra, ho usato il
ngSe altro
sintassi che è stata introdotta nell'ultima versione di Angular. Ecco come funziona:Contenuto valido ...Contenuto non valido ... Invia il modulo utilizzando ngSubmit
Abbiamo quasi finito il modulo. Ora dobbiamo essere in grado di inviare il modulo e il controllo dei dati del modulo deve essere trasferito su un metodo componente, ad esempio
onFormSubmit ()
.app / iscrizione-forma / iscrizione-form.component.ts