เมื่อเวลาเรากรอก หมายเลขเข้าไปสองช่อง แต่เราไม่อยากให้ซ้ำกัน จึงจะทำมาตรวจสอบ ว่าถ้าตรงให้ Complete ถ้าไม่ตรงให้ทำอะไร ใครกรอกทีหลังถ้าไปซ้ำก็จะมีข้อความแสดงออกมา
เริ่มต้นเราจะสร้างโปรเจคใหม่ ชื่อว่า check ไปที่ Terminal
ng new check
? Would you like to add Angular routing? (y/N) ตอบ y
? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS เลือก CSS
รอให้ขึ้นคำว่า
cd เข้าไปในโปรเจค
cd check
และเปิดโปรเจค จะไปเปิดที่ Visual Studio Code
code .
กด command + J แล้วรัน serve
ng serve
ไปเปิด port localhost:4200 ที่ Browser จะได้แบบนี้
จากนั้นไปที่ src > app > app.component.html ลบโค้ดออก และเอาชื่อมาแสดง และ ไปป์ ให้เป็นตัวใหญ่ (uppercase) แล้วบันทึก ดูผลลัพธ์อีกรอบ
ที่ไฟล์ app.component.html
<h1>{{title | uppercase}}</h1>
<router-outlet></router-outlet>
เพิ่มเติมที่ app.component.html หน้าตาเริ่มต้น
<h1>{{title | uppercase}}</h1><form>
<div>
<label>บัญชีของรายใหญ่</label>
<select>
<option> </option>
</select>
</div> <div>
<label>บัญชีของรายย่อย</label>
<select>
<option> </option>
</select>
</div>
</form><router-outlet></router-outlet>
ที่ไฟล์ app.module.ts แล้ว import ReactiveFormsModule เพื่อที่จะใช้ FormGroup , FormControl
import { ReactiveFormsModule } from ‘@angular/forms’;
และ imports มาใช้
imports: [
BrowserModule,
AppRoutingModule, ReactiveFormsModule,
],
ไปที่ไฟล์ app.component.ts
ประกาศตัวแปรมาตามตัว เก็บค่าดังนี้
form: FormGroup;parent$: Observable<string[]>;child$: Observable<string[]>;
เพิ่ม implements OnInit เอา Method ทั้งสองเข้ามาให้เรียบร้อย
export class AppComponent implements OnInit{title = 'check';form: FormGroup;
parent$: Observable<string[]>;
child$: Observable<string[]>;constructor(){}ngOnInit(){}
}
เอาตัวแปร parent$ , child$ เก็บ Data เพื่อที่จะเอาไปแสดงบน Templete ที่ ngOnInit()
ngOnInit(){ this.parent$ = of<string[]>([
'0123456789',
'0123456781'
]); this.child$ = of<string[]>([
'0123456789',
'0123456782',
'0123456783',
'0123456784',
'0123456785'
]);
}
** import { Observable, of } from ‘rxjs’; ต้องเป็น rxjs เน้อ
กลับไปที่ไฟล์ app.component.html เพื่อที่จะ data ไปแสดง
<h1>{{title | uppercase}}</h1><form [formGroup]="form">
<div>
<label>บัญชีของรายใหญ่</label>
<select>
<option *ngFor="let parent of parent$ | async">
{{parent}}
</option>
</select>
</div><div>
<label>บัญชีของรายย่อย</label>
<select>
<option *ngFor="let child of child$ | async">
{{child}}
</option>
</select>
</div>
</form><router-outlet></router-outlet>
ที่หน้า Browser ได้ Data มาแสดง แต่ยัง Error ถามหา FormControlName
ถ้าอย่างงั้นแล้ว เรากลับไปที่ไฟล์ app.component.ts
เพิ่มตัวแปร fb มีค่าเป็น FormBuilder ที่ constructor
constructor(private fb : FormBuilder,){}
แล้วเรียกใช้งาน
ngOnInit(){ this.form = this.fb.group({
parent: [''],
child : ['']
});}
แล้วไปที่ไฟล์ app.component.html เพิ่ม FormControlName= “” กับตัวแปรที่เราได้ประกาศไว้
<h1>{{title | uppercase}}</h1><form [formGroup]="form">
<div>
<label>บัญชีของรายใหญ่</label>
<select formControlName="parent">
<option *ngFor="let parent of parent$ | async">
{{parent}}
</option>
</select>
</div><div>
<label>บัญชีของรายย่อย</label>
<select formControlName="child">
<option *ngFor="let child of child$ | async">
{{child}}
</option>
</select>
</div>
</form><router-outlet></router-outlet>
กลับไปดูที่ Browser ปรากฏว่าหาย Error เพราะตรงตามรูปแบบของเขาแล้ว
เราจะเริ่มการตรวจสอบแล้วทีนี้ ว่าตรงกันไหม หรือไม่ตรงกัน
เรายังอยู่ ไฟล์ app.component.html และเพิ่ม Tag นี้ และตรวจสอบด้วย *ngIf ถ้าค่าเป็น true จะแสดงข้อความ ถ้าเป็น false จะไม่แสดงข้อความ
<h1>{{title | uppercase}}</h1><form [formGroup]="form">
<div>
<label>บัญชีของรายใหญ่</label>
<select formControlName="parent">
<option *ngFor="let parent of parent$ | async">
{{parent}}
</option>
</select>
<div class="dup" *ngIf="true">หมายบัญชีรายใหญ่ซ้ำกับบัญชีรายย่อย</div>
</div> <div>
<label>บัญชีของรายย่อย</label>
<select formControlName="child">
<option *ngFor="let child of child$ | async">
{{child}}
</option>
</select>
<div class="dup" *ngIf="fase">หมายบัญชีรายย่อยซ้ำกับบัญชีรายใหญ่</div>
</div>
</form><router-outlet></router-outlet>
ไปที่ไฟล์ app.component.css และเพิ่ม class .dup เสร็จแล้วบันทึก ไปดูผลลัพธ์ ที่ Browser กัน
.dup{
color: brown;
}
พอได้แบบนี้แล้ว ไปที่ไฟล์ app.component.ts กัน
ประกาศตัวแปร ที่เก็บค่า จาก form
get parent(): AbstractControl{return this.form.controls.parent};get child():AbstractControl{return this.form.controls.child};
แล้วเอาชื่อตัวแปรนี้ไปใช้ .hasError เพื่อตรวจสอบ ที่หน้า Template แทน true , false
<h1>{{title | uppercase}}</h1><form [formGroup]="form">
<div>
<label>บัญชีของรายใหญ่</label>
<select formControlName="parent">
<option *ngFor="let parent of parent$ | async">
{{parent}}
</option>
</select>
<div class="dup" *ngIf="parent.hasError('duplicate')">หมายบัญชีรายใหญ่ซ้ำกับบัญชีรายย่อย</div>
</div><div>
<label>บัญชีของรายย่อย</label>
<select formControlName="child">
<option *ngFor="let child of child$ | async">
{{child}}
</option>
</select>
<div class="dup" *ngIf="child.hasError('duplicate')">หมายบัญชีรายย่อยซ้ำกับบัญชีรายใหญ่</div>
</div>
</form><router-outlet></router-outlet>
ต่อไปกลับไปที่ไฟล์ app.component.ts เรากัน และเราจะเอาค่ามาตรวจสอบกัน
ngOnInit(){
this.parent.valueChanges
.pipe<string>(
switchMap(value => {
if(value === this.child.value){
console.log("Duplicate")
return NEVER;
}
return of(value);
})
) .subscribe(value => {
console.log("complete")
}); this.child.valueChanges
.pipe(
switchMap(value => {
if(value === this.parent.value){
console.log("Duplicate")
return NEVER;
}
return of(value);
})
)
.subscribe(value => {
console.log("complete")
});
}
บันทึกแล้วลองไปทดสอบดูว่า ถ้าค่าซ้ำกันจะแสดงข้อว่า “Duplicate” ถ้าไม่ซ้ำให้แสดงเป็น “complete” ไปดูกันที่ Browser
พอได้แบบนี้แล้ว เราจะทำของจริงล่ะ ให้แสดงข้อความขึ้นมาเมื่อซ้ำกัน
ไปที่ไฟล์ app.component.ts เพื่อที่จะ setErrors() เมื่อซ้ำกัน ด้วยข้อความที่เรา ได้บอกไว้ที่หน้า Templete ว่า duplicate (ช่องไหนกรอกทีหลังก็จแสดง ข้อความขึ้นมา)
ngOnInit(){
this.parent.valueChanges
.pipe<string>(
switchMap(value => {
if(value === this.child.value){
console.log("Duplicate")
this.parent.setErrors({duplicate:true});
return NEVER;
}
return of(value);
})
).subscribe(value => {
console.log("complete")
});this.child.valueChanges
.pipe(
switchMap(value => {
if(value === this.parent.value){
console.log("Duplicate")
this.child.setErrors({duplicate:true});
return NEVER;
}
return of(value);
})
)
.subscribe(value => {
console.log("complete")
});
}
ได้แล้ววว. แต่ยังไม่ค่อยสมบูรณ์เท่าไหร่ ไว้มาต่อกันครั้งต่อไป
ขอบคุณคุณครูขอบฉัน และเว็บนี้
โค้ดทั้งหมดของแต่ละไฟล์
app.module.ts
app.component.html
app.component.css
app.component.ts