handling forms in sayan unankard angular apps … · 2017-09-08 · 2 approaches •...
TRANSCRIPT
w w w . i t s c i . m j u . a c . t h / s a y a n
HANDLING FORMS IN ANGULAR APPS
SAYAN UNANKARD1/2560
3
ANGULAR AND FORMS
<form>
<label>name</label>
<input type=“text” name=“stuname”>
<label>email</label>
<input type=“text” name=“stuemail”>
<button type=“submit”>Save</button>
</form>
{
value : {
stuname : ‘sayan’,
stuemail : ‘[email protected]’
}
valid : true
}
2
2 APPROACHES
• Template-Driven โดยที่ Angular จะสรุปจาก (infers) form objects จาก DOM
• Reactive โปรแกรมเมอรตองเขียนโครงสรางดวย Typescript เพ่ือไปจัดการ DOM เอง
3
TEMPLATE-DRIVEN
ตองการสรางหนาจอสําหรับกรอกขอมูลดังน้ี
4
TEMPLATE-DRIVEN
ในสวนของ app.component.html สราง tag form โดยที่ไมตองระบุ action และ method
ดังนี้
<form><div id="user-data"><label for="username">Username</label><input type="text" id="username" class="form-control"><button class="btn btn-default" type="button">Suggest an
Username</button><label for="email">Mail</label><input type="email" id="email" class="form-control"><label for="secret">Secret Questions</label><select id="secret" class="form-control">
<option value="pet">Your first Pet?</option><option value="teacher">Your first teacher?</option>
</select></div><button class="btn btn-primary" type="submit">Submit</button>
</form>
หมายเหตุ css ไมไดกําหนดลงไปในตัวอยาง5
TEMPLATE-DRIVEN
ในการควบคุม Form สามารถกําหนด attribute โดยระบุ ngModel และ name เขาไปใน DOM
objects ดังนี้
<input type="text" id="username" class="form-control"ngModel name="username">
<input type="email" id="email" class="form-control“ngModel name="email">
<select id="secret" class="form-control" [ngModel]="defaultQuestion" name="secret">
<option value="pet">Your first Pet?</option><option value="teacher">Your first teacher?</option>
</select>
6
TEMPLATE-DRIVEN
ในสวนของปุม submit สามารถกําหนดใหเรียกใช method ที่สรางขึ้นมาได ดังนี้
เมื่อมีการกดปุม submit ใหไปเรียกใช method onSubmit() โดยสงคาตัวแปร frm เขาไป ซึ่งตัว
แปร frm ถูกกําหนดคาใหเปน ngForm
Method onSubmit() ใน ไฟล
app.component.ts
<form (ngSubmit)="onSubmit(frm)" #frm="ngForm">
import { Component} from '@angular/core';import { NgForm } from '@angular/forms';
@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})export class AppComponent {title = 'app works!';
onSubmit(frm : NgForm){console.log(frm);
}}
7
TEMPLATE-DRIVEN
8
TEMPLATE-DRIVEN
ตัวแปรประเภท local reference โดยใช @ViewChild แทนการสงพารามิเตอรใน onSubmit()
โดยเพิ่มตัวแปร @ViewChild() ในไฟล app.component.ts
<form (ngSubmit)="onSubmit()" #frm="ngForm">
import { Component, ViewChild } from '@angular/core';import { NgForm } from '@angular/forms';
@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})export class AppComponent {title = 'app works!';@ViewChild('frm') signfrm : NgForm;
onSubmit(){console.log(this.signfrm);
}} 9
VALIDATION TO CHECK USER INPUT
สามารถกําหนดรูปแบบการตรวจสอบการปอนขอมูลของผูใชได โดยการเพิ่ม attribute เชน
required หรือ email เขาไปใน INPUT objects
ในกรณีที่กรอกขอมูลไมถูกตองตามรูปแบบที่กําหนด attribute ที่ชื่อวา valid จะมีคาเปน false
<input type="text" id="username" class="form-control"ngModel name="username" required >
<input type="email" id="email" class="form-control"ngModel name="email" required email >
<input type="fullname" id="fullname" class="form-control"ngModel name="fullname" required pattern="[a-zA-Z ]*" >
10
VALIDATION TO CHECK USER INPUT
11
VALIDATION TO CHECK USER INPUT
โดยในสวนของ DOM elements จะมีการเพ่ิม attributes เชน ng-invalid ใน input object นั้น ๆ
ที่ผูใชกรอกขอมูลไมตรงรูปแบบ
12
VALIDATION TO CHECK USER INPUT
สามารถกําหนดใหปุม submit disabled ถาผูใชกรอกขอมูลไมถูกตองตามรูปแบบที่กําหนด
อีกทั้งยังสามารถกําหนดขอความแจงเตือนผูใชไดดังนี้
เพิ่มตัวแปร reference #email และใชคําส่ัง ngIf ในการตรวจสอบ properties ของ email วา
valid หรือไม และ email เคยเขาไปกรอกแลวหรือไม
<button class="btn btn-primary" type="submit" [disabled]="!frm.valid">Submit</button>
<label for="email">Mail</label><input type="email" id="email" class="form-control" ngModel name="email" required email #email="ngModel">
<span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>
13
VALIDATION TO CHECK USER INPUT
14
SET DEFAULT VALUE
การกําหนดคาเริ่มตนของ dropdown list ก็สามารถทําไดโดยการกําหนด property ดังนี้
<select id="secret"class="form-control" [ngModel]="defaultQuestion" name="secret">
<option value="pet">Your first Pet?</option><option value="teacher">Your first teacher?</option>
</select>
import { Component, ViewChild } from '@angular/core';import { NgForm } from '@angular/forms';
@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})export class AppComponent {defaultQuestion = 'pet';@ViewChild('frm') signfrm : NgForm;
...}
15
USING NGMODEL 2-WAYS BINDING
ในกรณีที่ตองการเพ่ิมคําตอบของคําถามลับ (Secret Question) สามารถกําหนดใหเปน 2-way
binding ได โดยใช ngModel ดังนี้<div class="form-group">
<textarea name="questionAnswer" rows=3 class="form-control" [(ngModel)]="answer"></textarea>
</div><p>Your reply : {{answer}}</p>
import { Component, ViewChild } from '@angular/core';import { NgForm } from '@angular/forms';...
export class AppComponent {defaultQuestion = 'pet';@ViewChild('frm') signfrm : NgForm;answer = '';
...}
16
USING NGMODEL 2-WAYS BINDING
17
HANDLING RADIO BUTTON
การจัดการ Radio button สามารถทําไดเชนเดียวกับ input อ่ืน ๆ โดยสามารถกําหนดคาดังน้ี
Loop แสดง radio buttom ตามคาใน genders array
export class AppComponent {@ViewChild('frm') signfrm : NgForm;defaultQuestion = 'pet';answer = '';genders = ['male', 'female'];
onSubmit(){console.log(this.signfrm);
}}
<div class="radio" *ngFor="let gender of genders"><label><input type="radio" name="gender" ngModel [value]="gender" required>{{ gender }}
</label></div>
18
BUTTON CLICK
การจัดการเมื่อมีการคลิกปุมที่ไมใช submit สามารถสราง method แลวเรียกใชดวยคําส่ัง (click)
ไดดังนี้
คําสั่ง this.signfrm.form.patchValue() เปนการเปล่ียนแปลงคาเฉพาะสวนที่ตองการ เพ่ือไมให
กระทบกับสวนอ่ืน ๆ ที่กรอกขอมูลไปแลว
suggestUserName() {const suggestedName = 'Superuser';this.signfrm.form.patchValue({username: suggestedName
});}
}
<button class="btn btn-default" type="button" (click)="suggestUserName()">Suggest an Username</button>
19
USING FORM DATA
การเรียกใชงานขอมูลจาก Form object สามารถทําไดโดยการประกาศตัวแปร เพ่ือเก็บคาขอมูล
จาก Form ไดดังนี้ โดยที่ชื่อตัวแปรไมจําเปนตองตรงกับชื่อของ form objects
การอานคาจาก Form สามารถทําไดโดยอางตัวแปร this.ชื่อตัวแปร form.value.ชื่อ form object
user = {username: '',email: '',secretQuestion: '',answer: '',gender: ''
};
onSubmit(){this.submitted = true;this.user.username = this.signfrm.value.username;this.user.email = this.signfrm.value.email;this.user.secretQuestion = this.signfrm.value.secret;this.user.answer = this.signfrm.value.questionAnswer;this.user.gender = this.signfrm.value.gender;
this.signfrm.reset();} 20
USING FORM DATA
สามารถเรียกดูคาจากตัวแปรท่ีรับคามาจาก form object ไดโดยแสดงผานทางหนาจอ ดังนี้
<hr><div class="row" *ngIf="submitted"><div class="col-xs-12"><h3>Your Data</h3><p>Username: {{ user.username }}</p><p>Mail: {{ user.email }}</p><p>Secret Question: Your first {{ user.secretQuestion }}</p><p>Answer: {{ user.answer }}</p><p>Gender: {{ user.gender }}</p>
</div></div>
21
EXERCISE
จงสรางหนาจอตอไปนี้โดยใช Angular4
22
REACTIVE APPROACH
Reactive approach เปนอีกวิธีการในการจัดการ Form ใน Angular <form><div class="form-group"><label for="username">Username</label><input type="text" id="username"class="form-control">
</div><div class="form-group"><label for="email">email</label><input type="text" id="email"class="form-control">
</div><div class="radio"
*ngFor="let gender of genders"><label><input type="radio"[value]="gender">{{ gender }}
</label></div><button class="btn btn-primary" type="submit">Submit</button>
</form>
23
REACTIVE APPROACH
ในสวนของ app.module.ts การทํางานดวย Reactive ไมจําเปนตองใช FormsModule แตจะใช
ReactiveFormsModule แทน
import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { FormsModule } from '@angular/forms';import { ReactiveFormsModule } from '@angular/forms';import { HttpModule } from '@angular/http';import { AppComponent } from './app.component';
@NgModule({declarations: [AppComponent
],imports: [BrowserModule,FormsModule,HttpModule,ReactiveFormsModule
],...
}) 24
REACTIVE APPROACH
การกําหนดคาระหวาง HTML และ Typescript สามารถทําไดดังนี้
ที่ไฟล app.component.ts ประกาศตัวแปร signupForm เปนตัวแปรประเภท FormGroup
จากนั้นสราง method ngOnInit() สําหรับกําหนดคาเร่ิมตนของ FormControl ตาง ๆ ในหนาจอ
export class AppComponent implements OnInit {genders = ['male', 'female'];signupForm: FormGroup;
ngOnInit() {this.signupForm = new FormGroup({'username': new FormControl(null),'email': new FormControl(null),'gender': new FormControl('male')
});}
}
25
REACTIVE APPROACH
ในสวนของหนาจอ html จะตองระบุชื่อของ form control ใหตรงกันกับในคลาส<form [formGroup]="signupForm"><div class="form-group"><label for="username">Username</label><input type="text" id="username" formControlName="username"class="form-control">
</div><div class="form-group"><label for="email">email</label><input type="text" id="email" formControlName="email"class="form-control">
</div><div class="radio" *ngFor="let gender of genders"><label><input type="radio" formControlName="gender"[value]="gender">{{ gender }}
</label></div><button class="btn btn-primary" type="submit">Submit</button>
</form>
26
REACTIVE APPROACH
ในกรณีที่ตองการเพิ่มการเรียกใชเมื่อมีการกดปุม submit สามารถกําหนด property ของ form ได
ดังนี้
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
onSubmit(){console.log(this.signupForm);
}
27
REACTIVE APPROACH FOR VALIDATION
การกําหนด Validation สําหรับตรวจสอบเงื่อนไขการกรอกขอมูลสามารถทําไดโดยกําหนด
Validator เชน Validator.required หรือ Validator.email เปนตน
ในกรณีที่ตองการแสดงขอความแจงเตือนสามารถกําหนดไดดังนี้
ngOnInit() {this.signupForm = new FormGroup({'username': new FormControl(null, Validators.required),'email': new FormControl(null, [Validators.required, Validators.email]),'gender': new FormControl('male')
});}
<span *ngIf="!signupForm.get('email').valid && signupForm.get('email').touched"
class="help-block">Please enter a valid email!</span>
28
ARRAY OF FORM CONTROL
ในกรณีที่ตองการสราง Form Control ที่มีลักษณะ Dynamic ตามความตองการของผูใช เชน หาก
ผูใชตองการเพ่ิมขึ้นมูลงานอดิเรก (Hobby) สามารถที่จะกรอกไดหลายรายการ
ขั้นตอนที่ 1 สราง formArrayName ชื่อวา hobbies โดยมีปุม Add และ loop แสดง Textbox
ตามจํานวนคร้ังที่กดปุม
<div formArrayName="hobbies"><h4>Your Hobbies</h4><button class="btn btn-default" type="button"
(click)="onAddHobby()">Add Hobby</button><div class="form-group" *ngFor="let hobbyControl of
signupForm.get('hobbies').controls; let i = index"><input type="text" class="form-control" [formControlName]="i">
</div></div>
29
ARRAY OF FORM CONTROL
ที่ method ngOnInit() เพ่ิมตัวแปร hobbies มีชนิดเปน FormArray
ขั้นตอนที่ 2 เพ่ิม method สําหรับกดปุม Add Hobby
ngOnInit() {this.signupForm = new FormGroup({'username': new FormControl(null, Validators.required),'email': new FormControl(null, [Validators.required, Validators.email]),'gender': new FormControl('male'),'hobbies': new FormArray([])
});}
onAddHobby() {const control = new FormControl(null, Validators.required);(<FormArray>this.signupForm.get('hobbies')).push(control);
}
30
31
ARRAY OF FORM CONTROL
ในสวนของการนําคาไปใชงานสามารถทําได ดังนี้
<hr><div class="row" *ngIf="submitted"><div class="col-xs-12"><h3>Your Data</h3><p>Username: {{ signupForm.value.username }}</p><p>Mail: {{ signupForm.value.email }}</p><p>Gender: {{ signupForm.value.gender }}</p><p>Hobbies: </p><div *ngFor="let hobby of signupForm.value.hobbies">
{{hobby}}</div>
</div>
32