การตรวจสอบค่า ว่าซ้ำกันไหม “pipe()”

Tawan_Ait
4 min readApr 23, 2020

--

เมื่อเวลาเรากรอก หมายเลขเข้าไปสองช่อง แต่เราไม่อยากให้ซ้ำกัน จึงจะทำมาตรวจสอบ ว่าถ้าตรงให้ Complete ถ้าไม่ตรงให้ทำอะไร ใครกรอกทีหลังถ้าไปซ้ำก็จะมีข้อความแสดงออกมา

ที่มา https://www.google.com/url?sa=i&url=https%3A%2F%2Fgroup.wunjun.com%2Fkhunsamatha%2Ftopic%2F605372-8827&psig=AOvVaw03nzVVKz4EcFz8mDHy3rwU&ust=1587741153422000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCODWq_jq_ugCFQAAAAAdAAAAABAs

เริ่มต้นเราจะสร้างโปรเจคใหม่ ชื่อว่า 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

--

--

No responses yet