บทความนี้เป็นส่วนหนึ่งของซีรีส์ Angular + PrimeNG 19 (CSR, non-standalone) เรียบเรียงจากคู่มืออบรมของ Wutthiphon Tassana — Wirabyte CO., LTD. — ตอนที่ 9/10
Service ใน Angular นั้นใช้สำหรับจัดการข้อมูลและการประมวลผลที่ไม่เกี่ยวข้องกับ UI โดยตรง เช่น การติดต่อ API (ทั้ง Restful/Web Socket หรืออื่น ๆ) กับเซิร์ฟเวอร์ , การจัดเก็บข้อมูลฝั่งผู้ใช้ (Local Storage / Session Storage) , การทำงานร่วมกับ RxJS เพื่อส่งข้อมูลหรือแจ้งอัปเดตให้ Component อื่น ๆ ที่ subscribe อยู่ โดยแนวคิดคือ ารแยก Business Logic ออกจาก Component ทำให้ Component มีหน้าที่แค่แสดงผล UI (Component ควรทำเฉพาะเรื่องของ UI ส่วน Service จัดการด้านข้อมูลทั้งหมด ทำให้โค้ดง่ายต่อการดูแลในระยะยาว)
การสร้างและใช้งาน Service
วิธีการสร้าง Service ใช้คำสั่ง
ng generate service <path/component name>
หรือ
ng g s <path/component name>
โดยเมื่อสร้างแล้วจะมี Folder ตามชื่อ Service ที่สร้างปรากฏขึ้นภายใต้ Folder src/app
เช่นสร้าง data Service
ng generate service services/data หากสามารถสร้างได้ ก็จะขึ้นว่า CREATE Service
สังเกต: จะมี Folder services ถูกสร้างขึ้นก่อนตามด้วย ไฟล์ data.service.ts (+.spec)
โดยเมื่อสร้างมาก็จะได้ไฟล์ลักษณะประมาณนี้ โดยชื่อของ Class จะมาตามชื่อของ Service ที่เราตั้งตามด้วยคำว่า “Service”
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class <ServiceName>Service {
constructor() { }
}
ตัวอย่าง Data Service
วิธีการเรียกใช้ใน Component
ให้ Import Service ที่ Component
จากนั้นเรียกใช้ที่ Constructor
จากนั้นก็สามารถเรียกใช้ Method ต่าง ๆ ใน Service ผ่านตัวแปรที่ประกาศไว้ที่ Constructor ได้เลย
this.<service>.<method>.?<service method action> การเรียกใช้งาน RESTful API
วิธีการเรียกใช้ข้อมูลจาก API ใน Angular จะใช้ Module HTTPClient ซึ่งมีติดมากับ Angular อยู่แล้ว โดยให้ Import provideHttpClient ที่ app.module ก่อน จากนั้นจึงค่อยเรียกใช้ Module HttpClient ที่ Service
app.module.ts
ที่ไฟล์ Service ให้ Import Module HttpClient และ Observable จาก rxjs
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
export class <ServiceName>Service {
constructor(private http: HttpClient) {}
}
จากนั้นให้ประกาศตัวแปร API_URL และ HTTP_OPTIONS เพื่อกำหนดเส้นทางและคุณลักษณะ API (สามารถประกาศที่ Service / Environment อื่น ๆ เพื่อให้สะดวกต่อการเรียกใช้)
const API_URL = '<API URL>';
const HTTP_OPTIONS = {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
};
เป็นการบอกว่า ให้ส่งข้อมูลไปหา API ในรูปแบบ JSON
คราวนี้ก็สามารถเรียกใช้ API ได้เลยผ่าน HttpClient โดยใน Service ให้เราทำการสร้าง Method แล้วเรียก API ดังนี้
<MethodName>(): Observable<any> {
return this.<HttpClient>.<method><any>(API_URL + '<sub path>',?{<body>}, HTTP_OPTIONS);
}
หากทราบประเภทข้อมูลที่จะ return กลับมาให้แทนที่ <any> ด้วย Interface ของข้อมูลที่จะ return กลับมาได้เลย
ตัวอย่าง (กรณีประกาศ HttpClient ให้เรียกผ่านตัวแปร http, คุณลักษณะ HTTP ใน HTTP_OPTIONS)
| HTTP Method | วิธีเรียกใช้ |
|---|---|
| GET | this.http..get(API_URL + ‘<sub path>’, HTTP_OPTIONS); |
| POST | this.http.post(API_URL + ‘<sub path>’,{body}, HTTP_OPTIONS); |
| PUT | this.http.put(API_URL + ‘<sub path>’,{body}, HTTP_OPTIONS); |
| PATCH | this.http.patch(API_URL + ‘<sub path>’,{body}, HTTP_OPTIONS); |
| DELETE | this.http..delete(API_URL + ‘<sub path>’ + <var>, HTTP_OPTIONS); |
ตัวอย่าง
วิธีเรียกใช้
ที่ Component ที่เราจะเรียกใช้งานให้ Import Service แล้วเรียกใช้ Service ผ่าน Method โดยใช้ method subscribe ของ Observable rxjs
this.<service>.<method>. subscribe({
next: (res) => {
// กระบวนการหลังจากได้ Response //
},
error: (err) => {
// กระบวนการหลังจากได้ Response //
}
})
next: (res) => {} เมื่อ request สำเร็จและมีการ response status 200 ข้อมูลจะอยู่ในส่วนนี้ error: (err) => {} เมื่อ request error และมีการ response status 400/500 ข้อมูลจะมาส่วนนี้แทน
🧪 LAB: ทดลองเรียกข้อมูลจาก API มาแสดงผล
ทดลองเรียกข้อมูลจาก Restful API ที่กำหนดให้มาแสดงผล
[Get] https://learning.wutthiphon.space/wutthiphon/api/ users
ข้อมูลที่จะ Return กลับมาเป็นข้อมูลผู้ใช้ 20 คน เป็น Array[] ประกอบด้วย
- birthday: string
- full_name: string
- gender: string
- password: string
- username: string
ให้เรียกข้อมูลแล้วเก็บข้อมูลเพื่อ Loop ด้วย *ngFor แสดงผลผ่าน UI
ทดสอบเรียกผ่าน Constructor เพื่อให้มีการโหลดทันทีที่มีการโหลดหน้า


ผลลัพธ์


ทดลองจัดให้อยู่ในรูปที่สวยงาม เช่นตาราง
Session Storage / Local Storage
บนเว็บเบราว์เซอร์สมัยใหม่ (Chrome, Firefox, Edge, Safari) มี Web Storage API ซึ่งใช้เก็บข้อมูลฝั่ง client แบบง่าย ๆ โดยแบ่งออกเป็น 2 ประเภทหลัก
- Local Storage
- เป็นพื้นที่เก็บข้อมูล ถาวร (persist) จนกว่าจะถูกลบ
- เหมาะสำหรับเก็บข้อมูลที่ไม่ลับมาก
- Session Storage
- เป็นพื้นที่เก็บข้อมูล ชั่วคราว สำหรับ session ปัจจุบันของ Browser Tab
- เมื่อปิด tab หรือ window ข้อมูลจะหาย
การใช้งาน Angular จะนิยมใช้ที่ Service โดยใช้ Method ในการดำเนินการต่าง ๆ โดยใช้ window.<local/session_storage> แบบเดียวกับ JavaScript ทั่วไป
วิธีการเรียกใช้สามารถ Import และเรียก Method ของ Service ผ่าน Component ได้เลย
this.tokenService.saveUsername('ADMIN');
console.log(this.tokenService.getUsername());
this.tokenService.clearUsername(); การ Update Component อื่นให้รับค่าใหม่
ใน Angular เราจะใช้ Subject / BehaviorSubject ของ rxjs ในการส่งค่าเมื่อเกิดการเปลี่ยนแปลง โดยหลักการคือให้ Component ติดตามตัวแปรไว้เมื่อเกิดการเปลี่ยนแปลง Service จะส่งข้อมูลใหม่ไปยัง Component ที่มีการติดตามไว้
โดยเริ่มจากให้ Import BehaviorSubject ที่ Service ที่ต้องการใช้งาน
import { BehaviorSubject } from 'rxjs';
จากนั้นสร้างตัวแปร BehaviorSubject โดยเริ่มต้นอาจเป็นค่าว่างไว้ก่อน
private <name> = new BehaviorSubject<string | null>(null);
กำหนดให้ส่งตัวแปรใหม่ไปยัง BehaviorSubject
this.<BehaviorSubject name>.next(‘<data>’);
สร้าง Method สำหรับให้ Component ติดตามไว้
public <MethodName>() {
return this.usernameSubject.asObservable();
}
ตัวอย่าง
เมื่อทำการเก็บ Username แล้วให้แสดงผลชื่อบน Header (Navbar)
token.service.ts
ทดลองเรียกใช้งานโดย Home Component จะเป็นการ Set ค่าแล้วให้แสดงผลที่ Navbar ของ Header
home.component.ts
home.component.html
template/header/header.component.ts
template/header/header.component.html
ผลลัพธ์
ก่อนคลิก “บันทึก Username” => ลองกรอกค่าแล้วบันทึก
เมื่อบันทึก => Navbar จะ Update และแสดงผลทันที (ในการใช้งานจริงบางกรณีอาจต้องใช้ ViewEncapsulation)
ที่ Console Log
ลองตรวจสอบตัวแปรผ่าน browser
เมื่อคลิก “ล้าง Username” => การแสดงผล Username บน Navbar จะหายไปตามเงื่อนไข
🧪 Final LAB: ทำหน้า Login เข้าสู่ระบบ
Concept: สร้าง Component login ใช้งานกับ path /login จากนั้นเขียนหน้าและระบบ login โดยให้มีการตรวจสอบการกรอกข้อมูลจากผู้ใช้ (Pre Validate) หากกรอก Username และ Password ไม่ครบให้มีข้อความแสดงบอก พร้อมกรอบสีแดงที่ Input หากกรอกครบแล้วคลิก Submit ให้ทำการส่งข้อมูลเพื่อทำการ Login โดยหาก Login สำเร็จให้มีการแสดงชื่อผู้ใช้พร้อมปุ่มออกจากระบบที่ Navbar แต่หากไม่สำเร็จให้แสดงข้อความ Error “ชื่อผู้ใช้งานหรือรหัสผ่านไม่ถูกต้อง”
Optional: Checkbox จดจำฉันให้เก็บข้อมูลใน localStorage โดยหาก Login สำเร็จให้เก็บ Username และ Password ชองผู้ใช้ไว้ เมื่อ User ออกจากระบบแล้วเข้าหน้า Login ให้ fill ข้อมูลใน Input อัตโนมัติ (พร้อมติ๊กว่าจดจำฉัน) หากนำออกหลัง Login สำเร็จให้ทำการลบค่าออก
Restful API สำหรับทดสอบการ Login
[POST] https://learning.wutthiphon.space/wutthiphon/api/auth/login/
ค่าที่ต้องส่งกรณีถูกต้อง
“username”: “user”
“password”: “P@ssw0rd”
**ทดลองการประยุกต์ใช้การแสดงผลกับ Prime NG โดยศึกษาผ่าน Document ของ Prime NG ได้เลยโดยจะถือเป็นคะแนนพิเศษ เช่นเมื่อ Login ผิดพลากให้ขึ้นข้อความและ toast และ dialog แจ้งเตือน การจัด form / layout ของหน้า ใช้ grid 12 ช่อง flex etc. การใช้ Input สำเร็จรูป p-inputtext p-password p-checkbox
[*** LAB นี้ไม่มีเฉลย ***]
ตัวอย่าง

กรณี ติ๊กจดจำฉัน

หลังเข้าสู่ระบบ (Design ด้วยตนเองได้เลย)
