ตามที่เราได้สร้าง service class ขึ้นมาแล้วในบทความตอนที่ผ่านมา
และเนื้อหาต่อไปนี้ เราจะมาทำการตั้งค่าเพื่อใช้งาน Injector กัน
(ทบทวนบทความได้ที่)
รู้จัก Dependency injection หรือการนำเข้า services ใน Angular
https://www.ninenik.com/content.php?arti_id=781 via @ninenik
ก่อนทำการนำ Injector ไปใช้งานใน Angular App เราต้องทำการตั้งค่าก่อน โดยการ
กำหนดค่า service class เข้าไปใน provider เพื่อแสดงหรือบอก Angular ว่า Injector นี้
เป็น service class ที่จำเป็นสำหรับ App ของเรา
ทำความเข้าใจง่ายๆ กล่าวคือ service class คือ class ใน Angular ที่เราสร้างขึ้นมาเพื่อ
ทำหน้าที่ใดๆ โดยก่อนที่จะไปทำงานภายใน App ของเราได้นั้น จะต้องทำการขึ้นทะเบียน
เป็นผู้ให้บริการก่อน การขึ้นทะเบียนเป็นผู้ให้บริการก็คือ การไปกำหนดค่าใน provider โดย
หลังจากขึ้นทะเบียนแล้ว service class ของเราก็จะกลายเป็น Injector ผู้ให้บริการ service
ภายใน App ยกตัวอย่างเช่น staff service ของเรา พอขึ้นทะเบียนเป็นผู้ให้บริการ โดยการกำหนด
ค่าใน provider แล้ว ก็จะกลายเป็น Injector ทำหน้าที่ให้บริการในการจัดหาข้อมูลรายชื่อ staff
ทั้งหมดมาใช้งานใน App แบบนี้เป็นต้น
การขึ้นทะเบียนผู้ให้บริการหรือ Provider นั้น สามารถทำได้ 2 วิธี
- การกำหนด provider ใน NgModule
- การกำหนด provider ใน App Component
โดยเลือกอย่างใดอย่างหนึ่ง ขึ้นกับขอบเขตการที่เราจะนำ Injector นั้นๆ ไปใช้งาน
1.การกำหนด provider ใน NgModule
เราสามารถขึ้นทะเบียน provider ไฟล์ app.module.ts โดยกำหนดค่าเป็นข้อมูลแบบ Array
เข้าไปใน providers metadata ของ @NgModule สมมติเรากำหนด StaffService ของเราลงไป
ส่วนนี้ ก็จะได้ไฟล์ app.module.ts เป็นดังนี้
ไฟล์ app.module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { UserComponent } from './components/user.component'; import { StaffFormComponent } from './components/staff-form.component'; import { StaffListComponent } from './components/staff-list.component' import { StaffService } from './components/staff.service' @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent, UserComponent, StaffFormComponent, StaffListComponent ], providers: [ StaffService ], bootstrap: [ AppComponent ] }) export class AppModule { }
การกำหนดค่าใน @NgModule ข้างต้น ก็จะทำให้ service class ของเรา เป็น Injector ที่สามารถ
นำไปใช้งานได้ทุกที่ภายใน App ของเรา
แต่เนื่องจาก StaffService ของเรานั้น ใช้งานเฉพาะในส่วนของ StaffListComponent เท่านั้น
ดังนั้น การกำหนดค่า provider ใน StaffListComponent จึงเป็นวิธีที่เหมาะสม ในการใช้งาน
ตัว Injector ตัวนี้ มากกว่าการกำหนดใน @NgModule
เราจึงเลือกวิธีที่ 2 ในการกำหนด provider สำหรับกรณีตัวอย่าง
2. การกำหนด provider ใน App Component
การขึ้นทะเบียน provider ใน Component มีวิธีการกำหนดแบบเดียวกับการกำหนดใน @NgModule
โดยการกำหนดค่าข้อมูลแบบ Array เข้าไปใน providers metadata ของ @Component ซึ่งใน
ตัวอย่างของเราคือ StaffListComponent ในไฟล์ staff-list.component.ts โดยสามารถกำหนด
ได้ดังนี้
ไฟล์ staff-list.component.ts
import { Component } from '@angular/core' import { Staff } from './staff' import { StaffService } from './staff.service' @Component({ moduleId: module.id, providers:[StaffService], selector: 'staff-list', templateUrl: `./staff-list.component.html`, }) export class StaffListComponent { }
การกำหนดใน @Component หรือใน Application Component นั้น จะทำให้ service class
เป็น Injector ที่สามารถเรียกใช้งานได้เฉพาะภายใน Component นั้นรวมถึง Component ลูก
ที่อยู่ภายใน Component น้้นด้วย
หมายเหตุ: ก่อนกำหนด service class ลงใน providers metadata ทุกครั้งเราต้องอย่าลืม
import service class นั้นๆ เข้ามาก่อนเสมอ ทั้งในกรณีกำหนดใน @NgModule หรือ @Component
ตามที่เราได้บอกไว้แล้วว่า เราจะใช้วิธีการกำหนด providers ใน @Component ต่อไปเราจะมา
ดูรายละเอียดเพิ่มเติม ในการเตรียมการสำหรับนำ Injector มาใช้งานใน App Component มีวิธี
การและการทำงานอย่างไร
การเตรียม StaffListComponent สำหรับใช้งาน Injector
ตามรูปแบบการใช้งาน DI ที่เราได้ศึกษามา StaffListComponent จะต้องทำการนำเข้า
StaffService โดยเรียกใช้งาน service ภายในฟังก์ชั่น constructor()
เรามาดูโค้ดเต็มของไฟล์ staff-list.component.ts ทั้งกรณีมีการใช้งาน DI หรือเรียกใช้ service
และกรณีไม่ได้ใช้งาน DI
ไฟล์ staff-list.component.ts
import { Component } from '@angular/core' import { Staff } from './staff' import { StaffService } from './staff.service' @Component({ moduleId: module.id, providers:[StaffService], selector: 'staff-list', templateUrl: `./staff-list.component.html`, }) export class StaffListComponent { staffs:Staff[]; constructor(staffService:StaffService){ this.staffs = staffService.getStaffs(); } }
import { Component } from '@angular/core' import { STAFFS } from './mock-staffs' @Component({ moduleId: module.id, selector: 'staff-list', templateUrl: `./staff-list.component.html`, }) export class StaffListComponent { staffs = STAFFS; }
ให้เราสังเกตให้ส่วนของการกำหนด parameter ใน constructor() จะพบว่า
parameter ที่เรากำหนดชื่อว่า staffService มี type หรือประเภทตัวแปรเป็น Service class
ที่ชื่อ StaffService ซึ่งการที่เราสามารถใช้งาน StaffService ได้ ก็เพราะว่าเรามีการขึ้น
ทะเบียน provider โดยการกำหนดใน @Component providers metadata
ดังนั้น ตัวแปร staffService จึงเป็นตัวแปรที่อ้างอิงถึง Injector ที่ชื่อ StaffService
โดยเมื่อใดที่ StaffListComponent มีการใช้งานเกิดขึ้น constructor() ก็จะทำการนำเข้า
StaffService เข้ามาใช้งานใน Component ทันที หลังจากนั้นใน constructor() ยังสั่งให้
staffService ทำคำสั่ง getStaffs() เพื่อดึงข้อมูลรายชื่อ staff มาไว้ในตัวแปร staffs
ดังตัวอย่างโค้ดในส่วนของบรรทัด
this.staffs = staffService.getStaffs();
เตือนความจำ: constructor() คือฟังก์ชั่นหรือคำสั่งที่ทำงานทันทีเมื่อ Component นั้นๆ
มีการใช้งาน โดยที่เราไม่ต้องเรียกใช้คำสั่ง เหมือนกรณีฟังก์ชั่นหรือคำสั่งอื่นๆ
ข้อสังเกต: การกำหนด parameter ใน construtor() ของ TypeScript จะเป็นกำหนด property
ของ Component ไปด้วยในตัว อย่างที่เราเคยเห็นในการกำหนดในไฟล์ staff.ts ดังนี้
export class Staff { constructor( public id: number, public name: string, public department: string, public age?: number ) { } }
ทีนี้เราได้เข้าใจวิธีการใช้งาน DI รวมถึงวิธีการขึ้นทะเบียน provider ไปแล้ว เนื้อหาต่อไป
เราจะยังอยู่เกี่ยวกับ DI จะลงไปดูรายละเอียดอื่นๆ เพิ่มเติม จะเป็นอะไนนั้นรอติดตามตอนหน้า