Det här är den andra delen av serien om introduktion till former i vinkel 4. I den första delen skapade vi en blankett med hjälp av den mallstyrda metoden. Vi använde direktiv som ngModel
, ngModelGroup
och ngForm
att överbelasta formelementen. I denna handledning tar vi ett annat sätt att bygga former - det reaktiva sättet.
Reaktiva blanketter tar en annan inställning jämfört med de mallstyrda formulären. Här skapar och initierar vi bilda kontrollobjekt i vår komponentklass. De är mellanliggande föremål som håller formens tillstånd. Vi binder dem sedan till bilda kontrollelement i mallen.
Formkontrollobjektet lyssnar på alla ändringar i ingångskontrollvärdena, och de reflekteras omedelbart i objektets tillstånd. Eftersom komponenten har direkt tillgång till datamodellstrukturen kan alla ändringar synkroniseras mellan datamodellen, formkontrollobjektet och ingångskontrollvärdena.
Praktiskt sett, om vi bygger ett formulär för uppdatering av användarprofilen, är datamodellen det användarobjekt som hämtas från servern. Enligt konventionen lagras det ofta i komponentens användaregenskap (this.user
). Formkontrollobjektet eller formulärmodellen kommer att vara bunden till mallens faktiska styrelement.
Båda dessa modeller ska ha liknande strukturer, även om de inte är identiska. Inmatningsvärdena bör dock inte direkt flöda i datamodellen. Bilden beskriver hur användarens inmatning från mallen går till formulärmodellen.
Låt oss börja.
Du behöver inte ha följt del 1 av den här serien, för del två är meningsfull. Men om du är ny på formulär i Angular, skulle jag verkligen rekommendera att gå igenom den mallstyrda strategin. Koden för det här projektet är tillgängligt på mitt GitHub-arkiv. Se till att du är på den högra grenen och sedan ladda ner zip eller, alternativt, klona repo för att se formuläret i aktion.
Om du föredrar att börja från början istället, se till att du har installerat Angular CLI. Använd ng
kommando för att skapa ett nytt projekt.
$ ng nytt SignupFormProject
Skapa sedan en ny komponent för SignupForm
eller skapa en manuellt.
ng generera komponent SignupForm
Ersätt innehållet i app.component.html med detta:
Här är katalogstrukturen för src / katalogen. Jag har tagit bort några icke-nödvändiga filer för att hålla sakerna enkla.
. ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── registreringsformulär │ │ ├ ─ - 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 för SignupForm
komponenten har skapats automatiskt. Det är där de flesta av vår kod kommer att gå. Jag har också skapat en ny User.ts
för att lagra vår användarmodell.
Innan vi dyker in i själva komponentmallen behöver vi ha en abstrakt idé om vad vi bygger. Så här är den formstruktur som jag har i mitt sinne. Anmälningsformuläret kommer att ha flera inmatningsfält, ett väljelement och en kryssruta.
Här är HTML-mallen som vi ska använda för vår registreringssida.
CSS-klasserna som används i HTML-mallen är en del av Bootstrap-biblioteket som används för att göra saker ganska. Eftersom detta inte är en designtutorial, kommer jag inte att prata mycket om CSS-aspekterna av formuläret om det inte behövs.
För att skapa en Reactive-formulär måste du importera ReactiveFormsModule
från @ kantiga / former
och lägg till den i importmatrisen i app.module.ts.
// Importera ReactiveFormsModule import ReactiveFormsModule från '@ vinkel / former'; @NgModule (... // Lägg till modulen till importen Arrayimport: [BrowserModule, ReactiveFormsModule ...) exportklass AppModule
Skapa sedan en användarmodell för registreringsformuläret. Vi kan antingen använda en klass eller ett gränssnitt för att skapa modellen. För denna handledning kommer jag att exportera en klass med följande egenskaper.
exportklass Användare id: nummer; email: string; // Båda lösenorden finns i ett enda objektlösenord: pwd: string; confirmPwd: string; ; kön: sträng; termer: booleska; konstruktör (värden: Objekt = ) // Konstruktorinitialisering Object.assign (detta, värden);
Skapa nu en förekomst av användarmodellen i SignupForm
komponent.
importera Component, OnInit från '@ vinkel / kärna'; // Importera användarnamporten Användare från './.../User'; @Component (selector: 'app-signup-form', templateUrl: './signup-form.component.html', styleUrls: ['./signup-form.component.css']) exportklass SignupFormComponent implementerar OnInit // Kön lista för välj kontrollelementet privat könLista: sträng []; // Egenskap för användarens privata användare: Användare; ngOnInit () this.genderList = ['Male', 'Female', 'Others'];
För registrering-form.component.html fil, kommer jag att använda samma HTML-mall som diskuterats ovan, men med mindre ändringar. Anmälningsformuläret har ett väljfält med en lista med alternativ. Även om det fungerar, kommer vi att göra det på vinkeln genom att slingra igenom listan med hjälp av ngFor
direktiv.
Obs! Du kan få ett fel som säger Ingen leverantör för ControlContainer. Felet visas när en komponent har en
Vi har en komponent, en modell och en formmall till hands. Vad nu? Det är dags att få våra händer smutsiga och bekanta med de API-er som du behöver för att skapa reaktiva former. Detta inkluderar FormControl
och FormGroup
.
Samtidigt som du bygger formulär med den reaktiva formulärstrategin kommer du inte att överträffa ngModel och ngForm-direktiven. I stället använder vi det underliggande FormControl and FormGroup API.
En FormControl är ett direktiv som används för att skapa en FormControl-instans som du kan använda för att hålla reda på ett visst formelements tillstånd och dess valideringsstatus. Så här fungerar FormControl:
/ * Importera FormControl först * / import FormControl från '@ vinkel / formulär'; / * Exempel på att skapa en ny FormControl-förekomst * / exportklass SignupFormComponent email = new FormControl ();
e-post
är nu en FormControl-förekomst, och du kan binda den till ett ingångskontrollelement i din mall enligt följande:
Bli Medlem
Mallformelementet är nu kopplat till FormControl-förekomsten i komponenten. Vad det betyder är någon förändring till ingångskontrollvärdet återspeglas i andra änden.
En FormControl-konstruktör accepterar tre argument - ett initialvärde, en rad synkroniseringsvaliderare och en rad async-validerare - och som du kanske har gissat är de alla valfria. Vi kommer att täcka de två första argumenten här.
importera Validators från '@ vinkel / formulär'; ... / * FormControl med inledande värde och en validator * / email = new FormControl ('[email protected] ', Validators.required);
Angular har en begränsad uppsättning inbyggda validatorer. De populära valideringsmetoderna inkluderar Validators.required
, Validators.minLength
, Validators.maxlength
, och Validators.pattern
. För att kunna använda dem måste du först importera Validator API.
För vår anmälningsblankett har vi flera inmatningskontrollfält (för e-post och lösenord), ett väljarkonto och ett kryssfält. Snarare än att skapa individ FormControl
objekt, skulle det inte vara mer meningsfullt att gruppera alla dessa FormControl
s under en enda enhet? Detta är fördelaktigt eftersom vi nu kan spåra värdet och giltigheten för alla delformskontrollobjekt på ett ställe. Det är vad FormGroup
är för. Så vi registrerar en förälder FormGroup med flera barn FormControls.
För att lägga till en FormGroup, importera den först. Därefter förklara signupForm som en klassegenskap och initiera den enligt följande:
// Importera API: n för att bygga en formulärimport FormControl, FormGroup, Validators från '@ angle / forms'; exportklass SignupFormComponent implementerar OnInit genderList: String []; signupForm: FormGroup; ... ngOnInit () this.genderList = ['Man', 'Female', 'Others']; this.signupForm = new FormGroup (email: new FormControl ("Validators.required), pwd: new FormControl (), confirmPwd: new FormControl (), gender: new FormControl (), terms: new FormControl ())
Bind FormGroup-modellen till DOM enligt följande: