פיתוח טפסים באפליקציה מבוססת אנגולר
ניתן לקרוא את הגרסה האנגלית של המדריך Angular form, NgForm and two-way data binding
אחד המרכיבים החשובים ביותר בכל אפליקציה הוא טופס ה-html שמאפשר למשתמשים אינטראקציה עם האתר. במדריך זה נלמד את הדרך של Angular לייצר טפסים חכמים ואינטר-אקטיביים במיוחד.
הדוגמה במודל היא טופס שלתוכו אנחנו מזינים את הפרטים של מודל מכונית, דוגמת שם המודל, והאם יש למכונית גג נפתח.
1. ניצור מחלקה CarModel
נתחיל מיצירת המחלקה CarModel, שמכילה את השדות של מודל המכונית, ולצורך כך נעזר ב-CLI. לחצו על הקישור כדי ללמוד כיצד להשתמש ב-CLI באפליקציה אנגולרית.
> ng generate class CarModel
export class CarModel {
constructor(public id : number,
public name: string,
public motor: string,
public hasSunroof : boolean
){}
}
המחלקה מכילה את השדות אתם נעבוד בטופס. מזהה המודל (id), שם המודל, סוג המנוע, והאם המודל מצויד בגג נפתח.
2. נייבא את ה-FormsModule
כדי לעבוד עם טפסים אנגולריים באפליקציה נייבא את ה FormsModule למודול השורש של האפליקציה.
app-module.ts
-----------------------
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
לא מספיק רק לייבא את המודול, צריך גם להוסיף אותו למערך imports.
3. נכתוב את הקוד שישמש את הקומפוננטה
נוסיף את הקוד הבסיסי לקובץ המחלקה של הקומפוננטה.
app.component.ts
-----------------------
import { Component } from '@angular/core';
import { CarModel } from './car-model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'car model';
motors = ['petrol', 'electric', 'unknown'];
carModel = new CarModel(1, '', '', false);
submitted = false;
onSubmit(){
this.submitted = true;
}
getCurrentModel() {
return JSON.stringify(this.carModel);
}
}
- המערך motors כולל סוגים שונים של מנועים (דלק, חשמל או לא יודע).
- האובייקט carModel מרחיב את הקלאס CarModel, והוא ריק כרגע. כי רק התחלנו.
- כשמגישים את הטופס המתודה onSubmit משנה את ערכו של המשתנה submitted מ-false ל-true.
- המתודה getCurrentModel מאפשרת לנו לעקוב אחרי המידע במודל בכל רגע.
4. נוסיף טופס ושדות לחלק ה-html של הקומפוננטה
app.component.html
---------------------------
<form>
<label>Name</label>
<input name="name" required>
<br />
<select name="motor" required>
<option *ngFor="let motor of motors" [value]="motor">{{motor}}</option>
</select>
<br />
<label><input type="radio" name="hasSunroof" value="true">Has sunroof</label>
<label><input type="radio" name="hasSunroof" value="false">No sunroof</label>
<br />
<input type="submit" value="Save">
</form>
- נקיף את הטופס בתגיות form כדי שאנגולר יזהה את הטופס.
- שמם של השדות בטופס ה-html הוא בהתאם לשם השדות במודל (name, model, hasSubroof).
- את רשימת הבחירה ניצור בתוך לולאת ngFor.
- השדות הכרחיים ולכן הוספנו להם required. זה מספיק כדי שאנגולר יטפל בולידציה של השדות.
5. נוסיף קשירה דו-כיוונית
כדי לגשת למידע בשדות נשתמש בקשירה דו-כיוונית. קשירה דו-כיוונית מאפשרת לשינויים בקוד להראות באופן פלאי בטופס, ולמידע שמזין המשתמש לטופס לעדכן מיד את קוד המחלקה.
תחביר הקשירה הדו-כיוונית הוא:
[(ngModel)]="fieldName"
כשה-fieldName הוא שמו של השדה בקוד הקומפננטה.
כדי שהקשירה תעבוד חובה להוסיף לשדה שם ייחודי.
<input type="text" name="name" [(ngModel)]="model.name">
השם הייחודי חיוני מפני שהוא מזהה את הקונטרול שממנו מגיע המידע.
נוסיף את הקשירה הדו-כיוונית לטופס בכך שנוסיף name ו-ngModel לכל שדה:
app.component.html
---------------------------
<form>
<label>Name</label>
<input name="name" [(ngModel)]="carModel.name" required>
<br />
<select name="motor" [(ngModel)]="carModel.motor" required>
<option *ngFor="let motor of motors" [value]="motor">{{motor}}</option>
</select>
<br />
<label><input type="radio" name="hasSunroof" [(ngModel)]="carModel.hasSunroof" [value]="true">Has sunroof</label>
<label><input type="radio" name="hasSunroof" [(ngModel)]="carModel.hasSunroof" [value]="false">No sunroof</label>
<br />
<input type="submit" value="Save">
</form>
6. עדכון המודל בזמן אמת
נשתמש במתודה getCurrentModel כדי לעקוב אחר מצב המידע במודל. לשם כך, נשבץ קריאה לפונקציה בתוך קובץ ה-html של הקונטרולר.
app.component.html
---------------------------
<pre>{{ getCurrentModel() }}</pre>
שימו לב, שבו בזמן זמן שאנחנו מזינים את הנתונים לשדות בטופס, מתעדכן המידע שמציגה הפונקציה getCurrentModel כי הקשירה הדו-כיוונית משנה מיד את המידע במודל.
7. NgForm
מכיוון שייבאנו את NgForm למודול השורש של האפליקציה בצעד השני, והקפדנו שהטופס ימצא בין תגיות form, אנגולר הלביש באופן אוטומטי את הדירקטיבה NgForm על הטופס. הדירקטיבה מחזיקה את המידע בטופס, ועוקבת אחרי מצב הזנת השדות, ומצב הולידציה של השדות ושל הטופס.
אנחנו יכולים לראות את השינוי במצב השדות אם נעקוב אחר השינוי בשמות הקלאסים שהאפליקציה הצמידה לכל שדה.
כדי לעקוב אחר המצב של אחד השדות נוסיף עליו local reference. לדוגמה, נוסיף local reference ששמו trackName על השדה name. נדפיס את הקלאסים מיד מתחת לשדה באופן הבא:
<input type="text" name="name" [(ngModel)]="carModel.name" required #trackName>
{{trackName.className}}
נרענן את הדף, ונראה את שמות הקלאסים שאנגולר צירף לשדות:
ng-untouched ng-pristine ng-invalid
- ng-untouched כי לא נגענו בשדה
- ng-pristine כי לא שינינו את ערך השדה
- ng-invalid כי השדה הוא שדה חובה, ועדיין לא הזנו ערך
נכנס לשדה, ונצא ממנו בלי לשנות את ערכו, ונקבל את שילוב הקלאסים הבא:
ng-pristine ng-invalid ng-touched
- ng-pristine כי לא שינינו את ערך השדה
- ng-invalid כי השדה הוא שדה חובה, ועדיין לא הזנו ערך
- ng-touched כי נכנסנו לתוך השדה
נקליד מספר תווים לתוך השדה, ואילו הקלאסים שנראה:
ng-touched ng-dirty ng-valid
- ng-touched כי נכנסנו לתוך השדה
- ng-dirty כי שינינו את ערך השדה
- ng-valid כי הערך עובר את הולידציה של required
כפי שניתן לעקוב אחר מצבם של השדות בטופס באמצעות local reference, ניתן לעקוב אחר כל הטופס באותה השיטה.
נוסיף את ה-local reference ששמו carModelForm על התגית הפותחת של הטופס:
<form #carModelForm="ngForm">
הצבת ה-ngForm כערכו של ה-local reference שמתייחס לטופס כולו מאפשרת לנו לעקוב אחר מצב הטופס באמצעות תכונות של המודול NgForm .
לדוגמה, בואו נבדוק מה יקרה כשנוסיף את הקוד הבא לטופס, שמאזין לתכונה value של ה-NgForm:
{{carModelForm.value | json}}
אנחנו יכולים לראות את ערכי השדות בטופס משתנים בזמן שאנחנו מזינים את הטופס.
אפשר גם לבדוק האם הטופס כולו ולידי על ידי האזנה לתכונה valid:
{{carModelForm.valid}}
מלמד אותנו האם הטופס ולידי. בהתאם לעובדה שכל השדות דרושים, נראה שכל עוד לא מילאנו את כל שלושת השדות מצב הטופס יהיה לא ולידי (ערך false). רק אחרי שנמלא את כל שלושת השדות יהפוך מצב הולידציה ל-true.
מיד נראה כיצד להשתמש במצבים השונים שנותן לנו הטופס האנגולרי בשביל להנחות את המשתמש בזמן מילוי הטופס, וגם כדי למנוע את הגשת הטופס במידה ואינו ולידי.
8. אינדיקציה והוראות למשתמש בזמן אמת
נוסיף פסקה שתציג הודעת שגיאה בתנאי שהשדה ריק, ולכן אינו ולידי, כי הוא מוגדר כ-required, ורק בתנאי שנכנסנו לשדה.
<input type="text" name="name" [(ngModel)]="carModel.name" required #trackName="ngModel">
<p class="alert" *ngIf="!trackName.valid && trackName.touched">The name is required</p>
כדי שהודעות השגיאה בזמן אמת יעבדו, הוספנו את הדירקטיבה ngModel על ה-local reference, שיש לה תכונות דוגמת valid, touched, pristine שאנחנו יכולים להיעזר בהם כדי להנחות את המשתמש באופן מדוייק.
ניתן גם להוסיף כללי CSS שיגרמו לשינוי מראה הטופס לפי מצבו. לדוגמה, הוספת קו אדום סביב השדות שאינם ולידיים ובתנאי שנגעו בהם.
.ng-invalid.ng-touched:not(form) {
border: 1px solid red;
}
9. הגשת הטופס
נגיש את הטופס באמצעות קשירת האירוע ngSubmit למתודה onSubmit בתוך הקוד.
<form (ngSubmit)="onSubmit()" #carModelForm="ngForm">
10. כיצד למנוע את הגשת הטופס אם אינו ולידי
ניתן למנוע הגשת טופס שאינו ולידי באמצעות קשירת התכונה disabled של הטופס למצב הטופס שאנחנו יכולים לדעת אותו כי אנחנו משתמשים ב-local reference לטופס, carModelForm.
<input type="submit" value="Save" [disabled]="!carModelForm.form.valid">
11. איפוס המודל והטופס
אפשר לאפס את הטופס, כולל מחיקת התוכן שהוזן לשדות, איפוס מצב הטופס, ומחיקת השדות במודל באמצעות המתודה reset.
<form (ngSubmit)="onSubmit(); carModelForm.reset()" #carModelForm="ngForm">
בתגובה לאירוע ngSubmit יופעלו שתי מתודות. השנייה היא המתודה reset שתאפס את הטופס והמודל בתגובה להגשת הטופס.
למדריכים נוספים בסדרת ה-Angular
אהבתם? לא אהבתם? דרגו!
0 הצבעות, ממוצע 0 מתוך 5 כוכבים
המדריכים באתר עוסקים בנושאי תכנות ופיתוח אישי. הקוד שמוצג משמש להדגמה ולצרכי לימוד. התוכן והקוד המוצגים באתר נבדקו בקפידה ונמצאו תקינים. אבל ייתכן ששימוש במערכות שונות, דוגמת דפדפן או מערכת הפעלה שונה ולאור השינויים הטכנולוגיים התכופים בעולם שבו אנו חיים יגרום לתוצאות שונות מהמצופה. בכל מקרה, אין בעל האתר נושא באחריות לכל שיבוש או שימוש לא אחראי בתכנים הלימודיים באתר.
למרות האמור לעיל, ומתוך רצון טוב, אם נתקלת בקשיים ביישום הקוד באתר מפאת מה שנראה לך כשגיאה או כחוסר עקביות נא להשאיר תגובה עם פירוט הבעיה באזור התגובות בתחתית המדריכים. זה יכול לעזור למשתמשים אחרים שנתקלו באותה בעיה ואם אני רואה שהבעיה עקרונית אני עשוי לערוך התאמה במדריך או להסיר אותו כדי להימנע מהטעיית הציבור.
שימו לב! הסקריפטים במדריכים מיועדים למטרות לימוד בלבד. כשאתם עובדים על הפרויקטים שלכם אתם צריכים להשתמש בספריות וסביבות פיתוח מוכחות, מהירות ובטוחות.
המשתמש באתר צריך להיות מודע לכך שאם וכאשר הוא מפתח קוד בשביל פרויקט הוא חייב לשים לב ולהשתמש בסביבת הפיתוח המתאימה ביותר, הבטוחה ביותר, היעילה ביותר וכמובן שהוא צריך לבדוק את הקוד בהיבטים של יעילות ואבטחה. מי אמר שלהיות מפתח זו עבודה קלה ?
השימוש שלך באתר מהווה ראייה להסכמתך עם הכללים והתקנות שנוסחו בהסכם תנאי השימוש.