Dette er den andre delen av serien om Introduksjon til skjemaer i vinkel 4. I den første delen opprettet vi et skjema ved hjelp av mal-drevet tilnærming. Vi brukte direktiver som ngModel
, ngModelGroup
og ngForm
å overlaste formelementene. I denne opplæringen tar vi en annen tilnærming til å bygge former - den reaktive måten.
Reaktive skjemaer tar en annen tilnærming enn i de malformede skjemaene. Her lager og initialiserer vi danner kontrollobjekter i vår komponent klasse. De er mellomliggende objekter som holder tilstanden til skjemaet. Vi vil da binde dem til danner kontrollelementer i malen.
Formkontrollobjektet lytter til enhver endring i inngangskontrollverdiene, og de reflekteres umiddelbart i objektets tilstand. Siden komponenten har direkte tilgang til datamodellstrukturen, kan alle endringer synkroniseres mellom datamodellen, skjemakontrollobjektet og inngangskontrollverdiene.
Praktisk sett, hvis vi bygger et skjema for oppdatering av brukerprofilen, er datamodellen brukerobjektet hentet fra serveren. Ved konvensjon lagres dette ofte inne i komponentens brukeregenskaper (this.user
). Skjemakontrollobjektet eller skjemamodellen vil være bundet til malens faktiske formelementer.
Begge disse modellene skal ha lignende strukturer, selv om de ikke er identiske. Imidlertid bør inngangsverdiene ikke direkte strømme inn i datamodellen. Bildet beskriver hvordan brukerinngangen fra malen gjør veien til skjemamodellen.
La oss komme i gang.
Du trenger ikke å ha fulgt del 1 av denne serien, for del to er fornuftig. Men hvis du er ny på skjemaer i Angular, vil jeg anbefale å gå gjennom den template-drevne strategien. Koden for dette prosjektet er tilgjengelig på mitt GitHub-depot. Sørg for at du er på den rette grenen og last ned zip-en, eller, klone repoen for å se skjemaet 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
eller opprett en manuelt.
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 å opprette et Reactive-skjema må du importere ReactiveFormsModule
fra @ vinkel / former
og legg det til importarmen i app.module.ts.
// Import ReactiveFormsModule import ReactiveFormsModule fra '@ vinkel / former'; @NgModule (... // Legg til modulen til importen Array import: [BrowserModule, ReactiveFormsModule ...) eksport klasse AppModule
Deretter oppretter du en brukermodell for registreringsskjemaet. Vi kan enten bruke en klasse eller et grensesnitt for å lage modellen. For denne opplæringen skal jeg eksportere en klasse med følgende egenskaper.
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);
Nå opprett en forekomst av brukermodellen i SignupForm
komponent.
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 // Kjønnsliste for velg kontrollelementet privat kjønnListe: streng []; // Egenskap for brukerens private bruker: Bruker; ngOnInit () this.genderList = ['Male', 'Female', 'Others'];
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.
Merk: Du kan få en feil som sier Ingen leverandør for ControlContainer. Feilen vises når en komponent har en
Vi har en komponent, en modell og en skjemamal for hånden. Hva nå? Det er på tide å få hendene skitne og bli kjent med APIene du trenger for å lage reaktive skjemaer. Dette inkluderer FormControl
og FormGroup
.
Mens du bygger formularer med den reaktive formstrategien, vil du ikke komme over ngModel og ngForm-direktiver. I stedet bruker vi den underliggende FormControl and FormGroup API.
En FormControl er et direktiv som brukes til å opprette et FormControl-eksempel som du kan bruke til å holde oversikt over et bestemt formelements tilstand og dens valideringsstatus. Slik fungerer FormControl:
/ * Import FormControl først * / import FormControl fra '@ vinkel / former'; / * Eksempel på å opprette en ny FormControl-forekomst * / eksportklasse SignupFormComponent email = new FormControl ();
e-post
er nå et FormControl-eksempel, og du kan knytte det til et input-kontrollelement i malen din som følger:
Melde deg på
Mallformelementet er nå bundet til FormControl-forekomsten i komponenten. Hva det betyr er en endring i inngangskontrollverdien blir reflektert i den andre enden.
En FormControl-konstruktør aksepterer tre argumenter - en innledende verdi, en rekke synkroniseringsvaliderere, og en rekke asynk-validatorer - og som du kanskje har gjettet, er de alle valgfrie. Vi vil dekke de to første argumentene her.
importere Validators fra '@ vinkel / former'; ... / * FormControl med innledende verdi og en validator * / email = new FormControl ('[email protected] ', Validators.required);
Angular har et begrenset sett med innebygde validatorer. Den populære valideringsmetoden inkluderer Validators.required
, Validators.minLength
, Validators.maxlength
, og Validators.pattern
. Men for å bruke dem må du først importere Validator API.
For vårt registreringsskjema har vi flere inngangskontrollfelt (for e-post og passord), et velg felt og et avkrysningsfelt. Snarere enn å skape individuelle FormControl
objekter, ville det ikke være mer fornuftig å gruppere alle disse FormControl
s under en enkelt enhet? Dette er gunstig fordi vi nå kan spore verdien og gyldigheten av alle sub-FormControl-objektene på ett sted. Det er hva FormGroup
er for. Så vi registrerer en foreldre FormGroup med flere barn FormControls.
For å legge til en FormGroup, importerer du først. Deretter erklærer du signupForm som en klasseegenskap og initialiserer den som følger:
// Importer API for å bygge en formular import FormControl, FormGroup, Validators fra '@ vinkel / former'; eksportklasse SignupFormComponent implementerer OnInit genderList: String []; signupForm: FormGroup; ... ngOnInit () this.genderList = ['Male', 'Female', 'Others']; this.signupForm = new FormGroup (email: new FormControl ("Validators.required), pwd: new FormControl (), confirmPwd: new FormControl (), kjønn: new FormControl (), vilkår: new FormControl ())
Bind FormGroup-modellen til DOM som følger: