Skjemaer er kritiske for enhver moderne front-end-applikasjon, og de er en funksjon som vi bruker hver dag, selv om vi ikke skjønner det. Skjemaer kreves for å logge inn på en bruker til appen, og søke etter alle tilgjengelige hoteller i en bestemt by, bestille en drosje, bygge en gjøremålsliste og gjøre tonnevis med andre ting vi er vant til. Enkelte skjemaer har bare et par inngangsfelt, mens andre skjemaer kan ha en rekke felt som strekker seg til et par sider eller faner.
I denne opplæringen snakker vi om ulike strategier som er tilgjengelige for å utvikle skjemaer i Angular. Uansett hvilken strategi du velger, er det de tingene som et skjemabibliotek bør dekke:
Angular, som er en fullverdig front-end rammeverk, har sitt eget sett med biblioteker for å bygge komplekse former. Den nyeste versjonen av Angular har to kraftige formbyggingsstrategier. De er:
Begge teknologiene tilhører @ vinkel / former
bibliotek og er basert på samme form kontroll klasser. Men de adskiller seg bemerkelsesverdig i sin filosofi, programmeringsstil og teknikk. Å velge den ene over den andre, avhenger av din personlige smak og også på kompleksiteten til skjemaet du prøver å skape. Etter min mening bør du prøve begge tilnærmingene først og velg en som passer til din stil og prosjektet ved hånden.
Den første delen av opplæringen vil dekke mal-drevne skjemaer med et praktisk eksempel: å bygge et registreringsskjema med validering for alle skjemafelter. I den andre delen av denne opplæringen vil vi gå tilbake til trinnene for å lage det samme skjemaet ved hjelp av en modelldrevet tilnærming i stedet.
Den mal-drevne tilnærmingen er en strategi som ble lånt fra AngularJS-epoken. Etter min mening er det den enkleste metoden for å bygge skjemaer. Hvordan virker det? Vi vil bruke noen kantede direktiver.
Direktivene lar deg legge til atferd til elementer i DOM.
- Angular Documentation
Angular gir formsspesifikke direktiver som du kan bruke til å binde skjemainngangsdata og modellen. De formsspesifikke direktivene legger til ekstra funksjonalitet og oppførsel til en vanlig HTML-skjema. Sluttresultatet er at malen tar seg av bindende verdier med modell og form validering.
I denne opplæringen bruker vi mal-drevne skjemaer for å opprette registreringssiden til et program. Skjemaet vil dekke de vanligste skjemaelementene og forskjellige valideringskontroller på disse skjemaelementene. Her er trinnene du vil følge i denne opplæringen.
app.module.ts
.ngModel
, ngModelGroup
, og ngForm
.ngSubmit
.La oss komme i gang.
Koden for dette prosjektet er tilgjengelig på min GitHub repo. Last ned postnummeret eller klon repoen for å se det i aksjon. Hvis du foretrekker å starte fra scratch i stedet, må du sørge for at du har installert Angular CLI. Bruke ng
kommandoen for å generere et nytt prosjekt.
$ ng ny SignupFormProject
Deretter genererer du en ny komponent for SignupForm.
ng generere komponent SignupForm
Erstatt innholdet i app.component.html med dette:
Her er katalogstrukturen for src / katalogen. Jeg har fjernet noen ikke-essensielle filer for å holde ting enkelt.
. ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── signup-form │ │ ├ ─ - 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
Som du kan se, en katalog for SignupForm
komponenten er opprettet automatisk. Det er der det meste av koden vår vil gå. Jeg har også laget en ny User.ts
for lagring av brukermodellen vår.
Før vi dykker inn i selve komponentmalen, må vi ha en abstrakt ide om hva vi bygger. Så her er formstrukturen som jeg har i tankene mine. Påmeldingsskjemaet vil ha flere inntastingsfelter, et valgelement og et avkrysningselement.
Her er HTML-malen som vi skal bruke til vår registreringsside.
CSS-klassene som brukes i HTML-malen, er en del av Bootstrap-biblioteket som brukes til å gjøre ting pent. Siden dette er ikke en designopplæring, snakker jeg ikke mye om CSS-aspektene av skjemaet med mindre det er nødvendig.
For å kunne bruke formulardirektiver, må vi importere FormsModule
fra @ vinkel / former
og legg det til import
array inn app.module.ts
.
importer FormModule fra '@ vinkler / skjemaer'; @NgModule (... import: [BrowserModule, FormsModule], ...) eksportklasse AppModule
Deretter oppretter du en klasse som vil holde alle egenskapene til brukerenheten. Vi kan enten bruke et grensesnitt og implementere det i komponenten eller bruke en TypeScript-klasse for modellen.
Eksportklasse Bruker id: nummer; e-post: streng; // Begge passordene er i et enkelt objektpassord: pwd: string; confirmPwd: string; ; kjønn: streng; vilkår: boolsk; konstruktør (verdier: Objekt = ) // Konstruktørinitialisering Object.assign (dette, verdier);
Lag nå en forekomst av klassen i SignupForm-komponenten. Jeg har også erklært en ekstra eiendom for kjønn.
importer Komponent, OnInit fra '@ vinkel / kjerne'; // Importer brukermodellimporten Bruker fra './.../User'; @Component (selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css']) eksportklasse SignupFormComponent implementerer OnInit // Egenskap for kjønn privat kjønn: streng []; // Egenskap for brukerens private bruker: Bruker; ngOnInit () this.gender = ['Male', 'Female', 'Others']; // Opprett et nytt brukerobjekt this.user = ny bruker (email: "), passord: pwd:" ", confirm_pwd:" ", kjønn: this.gender [0], vilkår: false);
For registrering-form.component.html fil, jeg skal bruke den samme HTML-malen diskutert ovenfor, men med mindre endringer. Påmeldingsskjemaet har et velgfelt med en liste over alternativer. Selv om det fungerer, vil vi gjøre det på den kantede måten ved å løpe gjennom listen ved hjelp av ngFor
direktiv.
Deretter ønsker vi å binde formdataene til brukerklasseobjektet slik at når du legger inn registreringsdataene i skjemaet, opprettes et nytt brukerobjekt som midlertidig lagrer dataene. På denne måten kan du holde synspunktet synkronisert med modellen, og dette kalles bindende.
Det er et par måter å få dette til å skje. La meg først introdusere deg til ngModel
og ngForm
.
ngForm og ngModel er kantede direktiver som er essensielle for å lage mal-drevne skjemaer. La oss begynne med ngForm
først. Her er et utdrag om ngForm fra Angular docs.
DeNgForm
Direktivet komplettererskjema
element med tilleggsfunksjoner. Den inneholder kontrollene du opprettet for elementene med enngModel
direktiv ogNavn
attributt, og overvåker deres egenskaper, inkludert deres gyldighet. Den har også sin egengyldig
eiendom som er sant bare hvis hver inneholdt kontroll er gyldig.
Først oppdaterer du skjemaet med ngForm
direktiv:
#signupForm
er en referansevariabel for mal som refererer til ngForm
direktiv som styrer hele skjemaet. Eksempelet nedenfor viser bruken av a ngForm
referanseobjekt for validering.
Her, signupForm.form.valid
vil returnere falsk med mindre alle formelementene overfører sine respektive valideringskontroller. Send-knappen vil bli deaktivert til skjemaet er gyldig.
Når det gjelder bindingen av malen og modellen, er det mange måter å gjøre dette på, og ngModel
har tre forskjellige syntakser for å takle denne situasjonen. De er:
La oss starte med den første.
[(NgModel)]
Utfører toveisbinding for å lese og skrive inngangskontrollverdier. Hvis en [(NgModel)]
Direktivet brukes, inputfeltet tar en startverdi fra den bundne komponentklassen og oppdaterer den tilbake når noen endring av inngangskontrollverdien oppdages (ved tastetrykk og knappetrykk). Bildet nedenfor beskriver toveis bindingsprosessen bedre.
Her er koden for e-post-feltet:
[(ngModel)] = "user.email"
binder brukerens e-postegenskap til inngangsverdien. Jeg har også lagt til en Navn attributt og sett name = "email"
. Dette er viktig, og du vil få en feil hvis du ikke har oppgitt et navnattributt mens du bruker ngModel.
Tilsvarende legg til en [(NgModel)]
og en unik Navn tilordne hvert formelement. Skjemaet ditt skal se slik ut nå:
......
De ngModelGroup
brukes til å gruppere sammen liknende skjemafelter, slik at vi bare kan kjøre valideringer på disse skjemafeltene. Siden begge passordfeltene er relaterte, vil vi sette dem under en enkelt ngModelGroup. Hvis alt fungerer som forventet, er komponentbundet bruker
Eiendom skal være ansvarlig for å lagre alle formkontrollverdiene. For å se dette i aksjon, legg til følgende etter skjemaetiketten:
user | json
Rør brukeregenskapen gjennom JsonPipe
å gjengi modellen som JSON i nettleseren. Dette er nyttig for feilsøking og logging. Du bør se en JSON-utgang som denne.
Verdiene flyter inn fra visningen til modellen. Hva med den andre veien? Prøv å initialisere brukerobjektet med noen verdier.
this.user = ny bruker (// initialisert med noen data e-post: "[email protected]", passord: pwd: "", confirm_pwd: "", kjønn: this.gender [0]);
Og de vises automatisk i visningen:
"email": "[email protected]", "passord": "pwd": "", "confirm_pwd": "", "kjønn": "Mann"
Den toveisbindende [(NgModel)]
syntaks hjelper deg å bygge skjemaer uten problemer. Det har imidlertid visse ulemper; Derfor er det en alternativ tilnærming som bruker ngModel
eller [NgModel]
.
Når ngModel
brukes, er vi faktisk ansvarlige for å oppdatere komponentegenskapen med inngangskontrollverdiene og omvendt. Inngangsdata flyter ikke automatisk inn i komponentens brukeregenskap.
Så erstatt alle forekomster av [(ngModel)] = ""
med ngModel
. Vi vil beholde Navn
attributt fordi alle tre versjonene av ngModel trenger Navn
attributt til arbeid.
Med ngModel
, verdien av navnetattributtet blir en nøkkel til ngForm-referanseobjektet signupForm
som vi opprettet tidligere. Så, for eksempel, signupForm.value.email
vil lagre kontrollverdien for e-post-ID.
Erstatte user | json
med signupForm.value | json
fordi det er der all staten er lagret akkurat nå.
Hva om du må sette innledende tilstand fra den bundne klassekomponenten? Det er det som [NgModel]
gjør for deg.
Her strømmer dataene fra modellen til visningen. Gjør følgende endringer i syntaksen for å bruke enveisbinding:
Så hvilken tilnærming bør du velge? Hvis du bruker [(NgModel)]
og ngForm
sammen, vil du til slutt ha to stater å opprettholde-bruker
og signupForm.value
-og det kan være potensielt forvirrende.
"email": "[email protected]", "passord": "pwd": "thisispassword", "confirm_pwd": "thisispassword", "gender": "Male" //user.value " e-post ":" [email protected] "," passord ": " pwd ":" thisispassword "," confirm_pwd ":" thisispassword "," gender ":" Male " //signupForm.value
Derfor vil jeg anbefale å bruke enveisbindingsmetoden i stedet. Men det er noe for deg å bestemme.
Her er våre krav til validering.
Den første er lett. Du må legge til en nødvendig
valideringsattributt til hvert formelement som dette:
Bortsett fra nødvendig
attributt, jeg har også eksportert en ny #email
Temperatur referansevariabel. Dette er slik at du kan få tilgang til inngangsruten Angular-kontroll fra selve malen. Vi vil bruke den til å vise feil og advarsler. Bruk nå knappens deaktiverte egenskap for å deaktivere knappen:
For å legge til en begrensning på e-post, bruk mønsterattributtet som fungerer med inntastingsfelter. Mønstre brukes til å angi regulære uttrykk som den nedenfor:
Mønsteret = "[a-Z0-9 ._% + -]. + @ [a-Z0-9 .-] + \ [a-z] 2,3 $"
For passordfeltet er alt du trenger å gjøre å legge til en minlength = ""
Egenskap:
For å vise feilene, skal jeg bruke betingelsesdirektivet ngIf
på et div-element. La oss starte med inngangskontrollfeltet for e-post:
E-postfeltet kan ikke være tomtE-post-ID-en virker ikke riktig
Det skjer mye her. La oss starte med den første linjen i feilseksjonen.
Husk
email.valid
,email.invalid
,email.dirty
,email.pristine
,email.touched
,email.untouched
, ogemail.errors
. Bildet nedenfor beskriver hver av disse egenskapene i detalj.Så div elementet med
* ngIf
vil bli gjengitt bare hvis e-postadressen er ugyldig. Brukeren vil imidlertid bli møtt med feil om at inntastingsfeltene er tomme selv før de har mulighet til å redigere skjemaet.For å unngå dette scenarioet har vi lagt til den andre betingelsen. Feilen vil bli vist bare etter kontrollen har blitt besøkt eller kontrollens verdi er endret.
De nestede div-elementene brukes til å dekke alle tilfeller av valideringsfeil. Vi bruker
email.errors
for å sjekke alle mulige valideringsfeil og deretter vise dem tilbake til brukeren i form av egendefinerte meldinger. Følg nå samme fremgangsmåte for de andre skjemaelementene. Slik har jeg kodet valideringen for passordene.app / registrering-skjema / registrering-form.component.html
Passordet må være over 8 tegnPassordene stemmer ikke overens Dette begynner å se litt rotete ut. Angular har et begrenset sett av validatorattributter:
nødvendig
,minlength
,maks lengde
, ogmønster
. For å dekke et annet scenario som for å sammenligne passord, må du stole på nestetngIf
conditionals som jeg gjorde ovenfor. Eller ideell, opprett en egendefinert valideringsfunksjon, som jeg vil dekke i tredje del av denne serien.I koden ovenfor har jeg brukt
ngIf annet
syntaks som ble introdusert i den siste versjonen av Angular. Slik fungerer det:Gyldig innhold ...Ikke gyldig innhold ... Send inn skjemaet ved hjelp av ngSubmit
Vi har nesten fullført skjemaet. Nå må vi kunne sende inn skjemaet, og kontrollen av skjemadataene skal overlevert til en komponentmetode, sier
onFormSubmit ()
.app / registrering-skjema / registrerings-form.component.ts