Inleiding tot formulieren in hoek 4 sjabloongestuurde formulieren

Wat je gaat creëren

Formulieren zijn van cruciaal belang voor elke moderne front-endapplicatie en ze zijn een functie die we elke dag gebruiken, zelfs als we ons dit niet realiseren. Formulieren zijn vereist voor het veilig inloggen bij een gebruiker van de app, het zoeken naar alle beschikbare hotels in een bepaalde stad, het boeken van een taxi, het bouwen van een takenlijst en het doen van talloze andere dingen die we gewend zijn. Sommige formulieren hebben slechts een paar invoervelden, terwijl andere formulieren een reeks velden kunnen hebben die zich uitstrekken tot een paar pagina's of tabbladen. 

In deze tutorial zullen we het hebben over verschillende strategieën die beschikbaar zijn voor het ontwikkelen van vormen in Angular. Ongeacht de strategie die u kiest, hier zijn de dingen die een formulierbibliotheek zou moeten omvatten:

  • Ondersteun de bidirectionele binding zodat de ingangscontrolewaarden synchroon lopen met de componentstatus.
  • Houd de formulierstatus bij en gebruik visuele aanwijzingen om de gebruiker te laten weten of de huidige status geldig is of niet. Als de gebruikersnaam bijvoorbeeld ongeldige tekens bevat, moet een rode rand rond het invoerveld voor de gebruikersnaam worden weergegeven.
  • Heb een mechanisme om validatiefouten correct weer te geven.
  • Schakel bepaalde delen van het formulier in of uit, tenzij aan bepaalde validatiecriteria is voldaan.

Inleiding tot vormen in hoekig

Hoekig, zijnde een volwaardig front-end framework, heeft zijn eigen verzameling bibliotheken voor het bouwen van complexe vormen. De nieuwste versie van Angular heeft twee krachtige strategieën voor het samenstellen van vormen. Zij zijn:

  • sjabloongestuurde formulieren 
  • modelgedreven of reactieve vormen

Beide technologieën behoren tot de @ Hoekige / formulieren bibliotheek en zijn gebaseerd op dezelfde formuliercontroleklassen. Ze verschillen echter opmerkelijk in hun filosofie, programmeerstijl en techniek. Het kiezen van een boven de ander hangt af van uw persoonlijke smaak en ook van de complexiteit van de vorm die u probeert te creëren. Naar mijn mening moet je eerst de twee benaderingen proberen en dan een kiezen die bij je stijl en het project past. 

Het eerste deel van de tutorial behandelt sjabloongestuurde formulieren met een praktisch voorbeeld: een aanmeldingsformulier bouwen met validatie voor alle formuliervelden. In het tweede deel van deze zelfstudie zullen we de stappen herhalen om dezelfde vorm te maken met behulp van een modelgestuurde aanpak. 

Sjabloon-gestuurde formulieren

De sjabloongestuurde aanpak is een strategie die is ontleend aan het AngularJS-tijdperk. Naar mijn mening is dit de meest eenvoudige methode om formulieren te bouwen. Hoe werkt het? We zullen enkele hoekige richtlijnen gebruiken. 

Met richtlijnen kunt u gedrag koppelen aan elementen in de DOM.
- Hoekige documentatie

Angular biedt formulespecifieke richtlijnen die u kunt gebruiken om de formulierinvoergegevens en het model te binden. De vormspecifieke richtlijnen voegen extra functionaliteit en gedrag toe aan een eenvoudig HTML-formulier. Het eindresultaat is dat de sjabloon zorgt voor bindende waarden met het model en formuliervalidatie. 

In deze zelfstudie gebruiken we sjabloongestuurde formulieren om de aanmeldingspagina van een toepassing te maken. Het formulier behandelt de meest voorkomende formulierelementen en verschillende validatiecontroles op deze formulierelementen. Dit zijn de stappen die u in deze zelfstudie zult volgen.

  • Voeg FormsModule toe aan app.module.ts.
  • Maak een klasse voor het gebruikersmodel.
  • Maak eerste componenten en lay-out voor het aanmeldingsformulier.
  • Gebruik richtlijnen voor hoekige formulieren zoals ngModelngModelGroup, en ngForm.
  • Validatie toevoegen met behulp van ingebouwde validators.
  • Validatiefouten zinvol weergeven.
  • Omgaan met formulierinzending met ngSubmit.

Laten we beginnen.

voorwaarden

De code voor dit project is beschikbaar op mijn GitHub-repo. Download de zip of kloon de repo om deze in actie te zien. Als u liever vanuit nul begint, zorg er dan voor dat u Angular CLI hebt geïnstalleerd. Gebruik de ng opdracht om een ​​nieuw project te genereren. 

$ ng nieuw SignupFormProject

Maak vervolgens een nieuw onderdeel voor het aanmeldingsformulier.

ng component Installatievorm genereren

Vervang de inhoud van app.component.html hiermee:

 

Hier is de mapstructuur voor de src / directory. Ik heb een aantal niet-essentiële bestanden verwijderd om de dingen eenvoudig te houden.

. ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── inschrijfformulier │ │ ├ ── 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 

Zoals je kunt zien, een map voor de SignupForm component is automatisch gemaakt. Dat is waar het grootste deel van onze code zal gaan. Ik heb ook een nieuw gemaakt User.ts voor het opslaan van ons gebruikersmodel.

De HTML-sjabloon

Voordat we in de eigenlijke componentsjabloon duiken, moeten we een abstract idee hebben van wat we aan het bouwen zijn. Dus hier is de vormstructuur die ik in gedachten heb. Het aanmeldingsformulier heeft meerdere invoervelden, een select element en een checkbox-element. 


Hier is de HTML-sjabloon die we zullen gebruiken voor onze registratiepagina. 

HTML-sjabloon

 
Inschrijven

De CSS-klassen die in de HTML-sjabloon worden gebruikt, maken deel uit van de Bootstrap-bibliotheek die wordt gebruikt om dingen mooier te maken. Omdat dit geen zelfstudie is, zal ik niet veel over de CSS-aspecten van de vorm praten, tenzij dat nodig is. 

Basic Form Setup

Om de sjabloongestuurde formulierrichtlijnen te gebruiken, moeten we het FormsModule van @ Hoekige / formulieren en voeg het toe aan de invoer array in app.module.ts.

app / app.module.ts

importeer FormsModule vanuit '@ angular / forms'; @ NgModule (... imports: [BrowserModule, FormsModule], ...) exportklasse AppModule  

Maak vervolgens een klasse die alle eigenschappen van de gebruikersentiteit bevat. We kunnen een interface gebruiken en deze implementeren in de component of een TypeScript-klasse voor het model gebruiken.

app / User.ts

exportklasse Gebruiker id: number; e-mail: string; // Beide wachtwoorden bevinden zich in een enkel objectwachtwoord: pwd: string; confirmPwd: string; ; geslacht: string; voorwaarden: boolean; constructor (waarden: Object = ) // Constructor-initialisatie Object.assign (this, values);  

Maak nu een exemplaar van de klasse in de component SignupForm. Ik heb ook een extra eigenschap voor het geslacht aangegeven. 

app / aanmelden-form / aanmelden-form.component.ts

importeer Component, OnInit uit '@ angular / core'; // Importeer het gebruikersmodel importeren Gebruiker uit './... / Gebruiker'; @Component (selector: 'app-signup-formulier', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css']) exporteer class SignupFormComponent implementeert OnInit // Eigenschap voor het geslacht privé-geslacht: tekenreeks []; // Eigenschap voor de gebruiker Privégebruiker: Gebruiker; ngOnInit () this.gender = ['Mannelijk', 'Vrouw', 'Andere']; // Maak een nieuw gebruikersobject this.user = nieuwe gebruiker (email: "", wachtwoord: pwd: "", confirm_pwd: "", geslacht: this.gender [0], terms: false);  

Voor de aanmelden-form.component.html bestand, ga ik dezelfde HTML-sjabloon gebruiken die hierboven is besproken, maar met kleine wijzigingen. Het aanmeldingsformulier heeft een select veld met een lijst met opties. Hoewel dat werkt, doen we het op de hoekige manier door de lijst door te lopen met behulp van de ngFor richtlijn.

app / aanmelden-form / aanmelden-form.component.html

Inschrijven...
...

Vervolgens willen we de formuliergegevens binden aan het gebruikersklasseobject, zodat wanneer u de registratiegegevens invoert in het formulier, er een nieuw gebruikersobject wordt gemaakt dat die gegevens tijdelijk opslaat. Op deze manier kunt u de weergave gesynchroniseerd houden met het model en dit wordt bindend genoemd. 

Er zijn een aantal manieren om dit te realiseren. Laat me je eerst even voorstellen ngModel en ngForm.

ngForm en ngModel

ngForm en ngModel zijn hoekige richtlijnen die essentieel zijn voor het maken van sjabloongestuurde formulieren. Laten we beginnen met ngForm eerste. Hier is een fragment over ngForm uit de Angular docs.

De NgForm richtlijn vult het het formulier element met extra functies. Het bevat de besturingselementen die u voor de elementen hebt gemaakt met een ngModel richtlijn en naam attribuut en controleert hun eigenschappen, inclusief hun geldigheid. Het heeft ook zijn eigen Geldig eigendom dat alleen waar is als elke ingesloten controle is geldig.

Werk eerst het formulier bij met de ngForm richtlijn:

app / aanmelden-form / aanmelden-form.component.html

...

#signupForm is een sjabloonreferentievariabele die verwijst naar de ngForm richtlijn die het volledige formulier beheert. Het onderstaande voorbeeld toont het gebruik van een ngForm referentieobject voor validatie.

app / aanmelden-form / aanmelden-form.component.html

Hier, signupForm.form.valid retourneert false tenzij alle formulierelementen hun respectievelijke validatiecontroles hebben doorstaan. De knop Verzenden is uitgeschakeld totdat het formulier geldig is.  

Wat betreft het binden van de sjabloon en het model, zijn er tal van manieren om dit te doen, en ngModel heeft drie verschillende syntaxes om deze situatie aan te pakken. Zij zijn:

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

Laten we beginnen met de eerste.

Tweerichtingsbinding met [(ngModel)]

[(NgModel)] voert tweewegsbinding uit voor het lezen en schrijven van invoerbesturingswaarden. Als een [(NgModel)] wordt gebruikt, neemt het invoerveld een initiële waarde van de gebonden componentklasse en werkt het opnieuw bij telkens wanneer een wijziging in de invoerbesturingswaarde wordt gedetecteerd (bij toetsaanslag en druk op de knop). De afbeelding hieronder beschrijft het bidirectionele bindproces beter.

Hier is de code voor het invoerveld voor e-mail:

 

[(ngModel)] = "user.email" bindt de e-maileigenschap van de gebruiker aan de invoerwaarde. Ik heb ook een toegevoegd naam attribuut en set name = "email". Dit is belangrijk en u krijgt een foutmelding als u geen naamkenmerk hebt opgegeven bij het gebruik van ngModel. 

Voeg ook een toe [(NgModel)] en een uniek naam attribuut aan elk formulierelement. Uw formulier zou er nu ongeveer zo uit moeten zien:

app / aanmelden-form / aanmelden-form.component.html

... 
...

De ngModelGroup wordt gebruikt om soortgelijke formuliervelden samen te groeperen, zodat we alleen validaties op die formuliervelden kunnen uitvoeren. Omdat beide wachtwoordvelden gerelateerd zijn, zullen we ze onder een enkele ngModelGroup plaatsen. Als alles naar verwachting werkt, is het component gebonden gebruiker eigenschap moet verantwoordelijk zijn voor het opslaan van alle formulierregelwaarden. Voeg het volgende toe na de formuletag om dit in actie te zien:

user | json

Leid de gebruikerseigenschap door de JsonPipe om het model als JSON in de browser weer te geven. Dit is handig voor foutopsporing en logging. Je zou een JSON-uitgang zoals deze moeten zien. 

De waarden stromen van het aanzicht naar het model. Hoe zit het andersom? Probeer het gebruikersobject met enkele waarden te initialiseren.

app / aanmelden-form / aanmelden-form.component.ts

this.user = nieuwe gebruiker (// geïnitialiseerd met een aantal gegevens e-mail: "[email protected]", wachtwoord: pwd: "", confirm_pwd: "", geslacht: this.gender [0]);

En ze verschijnen automatisch in de weergave:

"email": "[email protected]", "password": "pwd": "", "confirm_pwd": "", "gender": "Male"

De binding in twee richtingen [(NgModel)] syntaxis helpt u moeiteloos formulieren te bouwen. Het heeft echter bepaalde nadelen; daarom is er een alternatieve benadering die gebruikt ngModel of [NgModel].

Toevoegen van ngModel aan de mix

Wanneer ngModel wordt gebruikt, zijn we in feite verantwoordelijk voor het bijwerken van de componenteigenschap met de invoerbesturingswaarden en omgekeerd. De invoergegevens vloeien niet automatisch over in de gebruikerseigenschap van de component.

Vervang dus alle exemplaren van [(ngModel)] = "" met ngModel. We zullen de naam attribuut omdat alle drie de versies van ngModel de naam attribuut aan het werk. 

app / aanmelden-form / aanmelden-form.component.html

Met ngModel, de waarde van het naamkenmerk wordt een sleutel van het ngForm-referentieobject signupForm die we eerder hebben gemaakt. Dus bijvoorbeeld, signupForm.value.email slaat de controlewaarde voor de e-mail-ID op. 

Vervangen user | json met signupForm.value | json omdat daar nu alle staat is opgeslagen. 

One-Way Binding met [ngModel]

Wat als u de beginstatus van de gebonden klassencomponent moet instellen? Dat is wat de [NgModel] doet voor jou. 

Hier stromen de gegevens van het model naar het beeld. Breng de volgende wijzigingen aan in de syntaxis om one-way binding te gebruiken:

app / aanmelden-form / aanmelden-form.component.html

Dus welke aanpak zou je moeten kiezen? Als je gebruikt [(NgModel)] en ngForm samen zul je uiteindelijk twee staten hebben om te behouden-gebruiker en signupForm.value-en dat kan mogelijk verwarrend zijn. 

"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 

Daarom zal ik aanbevelen om in plaats daarvan de one-way binding-methode te gebruiken. Maar dat is iets voor u om te beslissen.

Validatie en weergave van foutmeldingen 

Dit zijn onze vereisten voor de validatie.

  • Alle formulierbesturingselementen zijn verplicht.
  • Schakel de knop Verzenden uit totdat alle invoervelden zijn gevuld.
  • Het e-mailveld moet een e-mail-ID bevatten.
  • Het wachtwoordveld moet een minimale lengte van 8 hebben.
  • Zowel het wachtwoord als de bevestiging moeten overeenkomen.
Ons formulier met validatie op zijn plaats

De eerste is eenvoudig. Je moet een toevoegen verplicht validatieattribuut aan elk formulierelement zoals dit:

app / aanmelden-form / aanmelden-form.component.html

Los van de verplicht attribuut, ik heb ook een nieuw geëxporteerd #email sjabloonreferentievariabele. Dit is zodat u vanuit de sjabloon zelf toegang hebt tot de hoekbesturing van het invoervak. We zullen het gebruiken om fouten en waarschuwingen weer te geven. Gebruik nu de gedeactiveerde eigenschap van de knop om de knop uit te schakelen:

app / aanmelden-form / aanmelden-form.component.html

Om een ​​beperking op e-mail toe te voegen, gebruikt u het patroonattribuut dat werkt met invoervelden. Patronen worden gebruikt om reguliere expressies zoals die hieronder te specificeren:

pattern = "[a-z0-9 ._% + -]. + @ [a-Z0-9 .-] + \ [a-z] 2,3 $"

Voor het wachtwoordveld hoeft u alleen maar een toe te voegen minlength = "" attribuut:

app / aanmelden-form / aanmelden-form.component.html

 

Om de fouten weer te geven, ga ik de voorwaardelijke richtlijn gebruiken ngIf op een div-element. Laten we beginnen met het invoerveld voor e-mail:

app / aanmelden-form / aanmelden-form.component.html

Het e-mailveld mag niet leeg zijn
Het e-mailadres lijkt niet goed

Er gebeurt hier veel. Laten we beginnen met de eerste regel van het foutgedeelte.

Herinner de #email variabele die we eerder hebben geëxporteerd? Het bevat enige hoeveelheid informatie over de invoerbesturingsstatus van het e-mailveld. Dit bevat: email.valid, email.invalid, email.dirty, email.pristine, email.touched, email.untouched, en email.errors.  De onderstaande afbeelding beschrijft elk van die eigenschappen in detail.

Dus het div element met de * ngIf wordt alleen weergegeven als de e-mail ongeldig is. De gebruiker zal echter worden begroet met fouten over de lege invulvelden, zelfs voordat ze de kans hebben om het formulier te bewerken. 

Om dit scenario te voorkomen, hebben we de tweede voorwaarde toegevoegd. De fout wordt pas daarna weergegeven de besturing is bezocht of de waarde van de controle is veranderd.

De geneste div-elementen worden gebruikt voor alle gevallen van validatiefouten. We gebruiken email.errors om alle mogelijke validatiefouten te controleren en deze vervolgens weer te geven aan de gebruiker in de vorm van aangepaste berichten. Volg nu dezelfde procedure voor de andere formulierelementen. Hier is hoe ik de validatie voor de wachtwoorden heb gecodeerd. 

app / aanmelden-form / aanmelden-form.component.html

 
Wachtwoord moet uit meer dan 8 tekens bestaan
Wachtwoorden komen niet overeen

Dit begint een beetje rommelig te lijken. Angular heeft een beperkte set validatorattributen: verplicht, minimale lengte, maximale lengte, en patroon. Om een ​​ander scenario als dat van wachtwoordvergelijking te dekken, moet u vertrouwen op genest ngIf conditionals zoals ik hierboven deed. Of maak idealiter een aangepaste validatiefunctie die ik in het derde deel van deze serie zal behandelen.

In de bovenstaande code heb ik de anders syntaxis die is geïntroduceerd in de nieuwste versie van Angular. Hier is hoe het werkt:

Geldige inhoud ...
Niet geldige inhoud ...

Dien het formulier in met behulp van ngSubmit

We zijn bijna klaar met het formulier. Nu moeten we het formulier kunnen indienen en de controle van de formuliergegevens moet bijvoorbeeld worden overgedragen aan een componentmethode onFormSubmit ().

app / aanmelden-form / aanmelden-form.component.ts

...

Nu, voor de component:

app / aanmelden-form / aanmelden-form.component.ts

... public onFormSubmit (value, valid: value: User, valid: boolean) this.user = waarde; console.log (this.user); console.log ("geldige:" + geldig);  ... 

Laatste demo

Hier is de definitieve versie van de applicatie. Ik heb een paar bootstrap-klassen toegevoegd om de vorm mooi te maken.

Samenvatting

We zijn hier allemaal klaar. In deze zelfstudie hebben we alles besproken wat u moet weten over het maken van een formulier in Angular met behulp van de sjabloongestuurde aanpak. Sjabloongestuurde vormen zijn populair vanwege hun eenvoud en gebruiksgemak. 

Als u echter een formulier met veel vormelementen moet bouwen, wordt deze aanpak rommelig. In de volgende tutorial behandelen we dus de modelgestuurde manier om hetzelfde formulier te maken. 

Deel uw mening in de reacties hieronder.

Leer JavaScript: de complete gids

We hebben een complete handleiding samengesteld om u te helpen JavaScript te leren, of u net bent begonnen als een webontwikkelaar of dat u meer geavanceerde onderwerpen wilt verkennen.