Basic Angular Leaning[2]
https://nunthineetp.medium.com/basic-anuglar-learning-1-f688bbc7c820
จากบทความที่แล้ว เราพูดถึง TypeScript พื้นฐานแบบคร่าวๆ ไปแล้ว ในบทความนี้เราจะเข้าสู่เนื้อหา Angular กัน
เตรียม Environment สำหรับก่อนสร้างโปรเจค Angular
โปรแกรม Visual Studio Code ใช้สำหรับการพัฒนา
download : https://code.visualstudio.com/download
Node.js
Node.js คือ Runtime Built สำหรับภาษา JavaScript
download : https://nodejs.org/en/download/
node -v //พิมพ์คำสั่งใน cmd เพื่อเช็คว่าติดตั้งสมบูรณ์
ติดตั้ง Angular CLI
Angular CLI เป็น Command line interface ที่ช่วยให้เราสามารถเขียน Angular ได้
npm install -g @angular/cli@latest
npm install --save-dev @angular-devkit/build-angularตรวจสอบว่าติดตั้งสมบูรณ์หรือยังด้วยการเช็คเวอชั่น
ng v
ติดตั้ง TypeScript
npm install typescript --save-dev
ทดลองสร้างโปรเจค Angular
สร้างโปรเจค Angular ด้วยคำสั่ง
ng new <project-name>
เมื่อเปิดดูไฟล์ที่ Angular CLI สร้างขึ้นมาให้ก็จะเห็นโครงสร้างประมาณนี้
รัน Angular ด้วยคำสั่ง
ng serve //หรือ ng s
ถ้ารันสำเร็จไม่มีข้อผิดพลาด ก็จะแสดง Compiled Successfully. ดังรูป และเปิด http://localhost:4200/
โครงสร้างเบื้องต้น
Index.html
Browser จะเห็นแค่ index.html เท่านั้น โดย angular จะสลับ component ที่ต้องการแสดงให้เอง
Package.json
เปรียบเสมือนบัตรประจำตัวของโปรเจค เช่น โปรเจคชื่ออะไร เวอชั่นเท่าไร ใช้ dependency อะไรบ้าง
Angular.json
เก็บ Config สำหรับ Angular Project เช่น Environtment
Main.ts
เป็นตัวกำหนดว่าจะให้ใครเป็น Root Module ในระบบ
Angular มีคอนเซปที่แบ่งสิ่งต่างๆ ที่เกี่ยวข้องกันออกเป็น Module ย่อยๆ โดยต้องมีอย่างน้อยหนึ่ง Module หลัก (Root Module)
Assets Directory
เก็บของที่จะใช้ในระบบ เช่น รูปภาพ font ฯลฯ
Environtment
เก็บการตั้งค่าที่ใช้ในการ Serve หรือ Build โปรเจค
E2E
คือ Unit Test ของ Angular
“All app has, at least, one module: the root one “
Module
- ใช้ @NgModule decorators ที่ใช้ระบุว่า class นี้เป็น module
- ทำหน้าที่รวบรวม Component, Diectives, Pipes และ Services ที่เกี่ยวข้องไว้ด้วยกัน
Angular ใช้ Decorators ในการระบุว่าควรจะ Compile Class นี้ยังไง (เหมือนใช้บอกว่ามันเป็นใคร ทำอะไร) เราจะเห็นมันเป็น class ธรรมดา จนกระทั่งเราแนบ Decorator ไปบอก Angular ว่า Class นี้เป็น Module นะ เป็น Component นะ
Properties ที่สำคัญ
Declarations
สำหรับประกาศ View Class (Component, Directive, Pipe) ที่อยู่ภายใน Module
Imports
สำหรับนำเข้า Module จากภายนอก เข้ามาใช้ภายใน Module ของเรา ยกตัวอย่างเช่น dependency ต่างๆ
Providers
สำหรับประกาศ Service ที่จะใช้ เพื่อให้ Class อื่นๆ ภายใต้ สามารถใช้ได้ด้วย
Bootstrap
กำหนดว่าจะให้ Component ไหนเป็น Component เริ่มต้นการทำงานของ Module (เฉพาะ Root Module เท่านั้น)
Exports
ส่งออก Class ภายใน Module ของตัวเอง ไปให้ Module อื่น ๆ ใช้งานได้
Componet
- ใช้ @Component กำกับ
- ทำหน้าที่ควบคุมการทำงานของ View Template (HTML) ผ่านทาง Properties (ตัวแปร) และ Function
Properties ที่สำคัญ
Selector
ชื่อที่อ้างถึง Component ที่ใช้บน HTML Template
selector จะบอกAngular ว่าให้สร้าง และเพิ่ม instance ของ Component นี้ เมื่อเจอTag ที่ตรงกับใน selector
TemplateURL
ไฟล์ HTML Template ที่ Component นี้ Support
StytleUrl
ไฟล์ CSS ที่ Component นี้ Support
Template
- เป็นหน้าจอแสดงผล มีลักษณะเดียวกับ HTML แต่สามารถใช้ Angular Syntax ได้ด้วย
Directives หรือ Annotation
- มี @Directive กำกับ
- เป็น metadata แบบหนึ่ง ที่มีหน้าีท่บอกว่าจะให้แสดง Template ออกมาแบบไหน
- Component เป็น Directive รูปแบบหนึ่ง ที่มี View เป็นของตัวเอง
มี 2 ประเภท
- Strctural Directives
ประเภทนี้จะเปลี่ยนแปลง Layout ของ DOM โดยการ เพิ่ม/ลบ/เปลี่ยน การแสดงผล เช่น *ngIF , *ngFor, *ngSwitch
2. Attribute Directives
ประเภทนี้จะเปลี่ยนรูปร่างหน้าตาหรือพฤติการณ์การทำงานของ DOM element เช่น ngModel, ngStyle, ngClass
Data Binding
เป็นการติดต่อสื่อสารระหว่าง View Template และ Component (HTML <-> TS)
แบ่งเป็น 2 แบบ
One-Way Data binding
การติดต่อทางเดียว คือ ส่งไป ไม่มีได้รับกลับ
- String Interpolation (การแทรกข้อความลงใน HTML)
=> {{ variable}}
// TypeScript
export class AppComponent{ title = 'Hello World'
}// HTML
<div> {{ title }} </div>
2. Property Binding (ผูกค่ากับ Property ของ Element)
=> [ variable ]
// TypeScript
export class AppComponent{ isActive = true
}//HTML
<button [disabled]="!isActive" > ADD </button>or <div [property]="value" </div>
3. Event Binding
ส่ง event จากฝั่ง HTML ไปยัง Component เช่น เมื่อกดคลิกแล้ว จะให้ทำอะไร
=> (….)
//HTML
<button (click)="print()" >Print</button>//TS
export class AppComponent{ print(){
console.log('hello')
}
}
Two-Way Binding
การผูกข้อมูลกลับไปมา ระหว่าง Component และ HTML
=> [(…)]
// TypeScript
export class AppComponent{ title = 'Hello World'
}// HTML
<input type="text" [(ngModel)]="title">
อธิบายเพิ่มเติม เราประกาศค่าเริ่มต้น title ไว้คือคำว่า ‘Hello World’ ทีนี้เมื่อฝั่ง HTML เกิด event ซึ่งก็คือการพิมพ์ข้อความใน input ค่าที่พิมพ์ใหม่นั้นก็จะส่งกลับมาที่ตัวแรก title ในฝั่ง TS นั่นเอง
Service
- มี @Service กำกับไว้
- เป็น Class ตัวกลางที่ไว้ใช้แชร์ข้อมูลร่วมกันระหว่าง Component, Directive, Pipe และ Service
Dependency Injection
เป็นเทคนิคที่ใช้ในการส่งต่อ (inject) dependency แทนการสร้างขึ้นมาใหม่ สามารถ Inject Service ได้หลายวิธี เช่นผ่านทาง Provider หรือ Constructor
ข้อดี คือทำให้การทำงานระหว่าง Class ไม่มีการผูกมัดกัน
Injector เป็นผู้ดูแลกล่องเก็บ Service (Container) ถ้า Service ที่มีคนขอใช้นั้นมีอยู่ในกล่องอยู่แล้ว Injector จะส่งต่อ Service นั้นไปให้ใช้ แต่ถ้าไม่มีมันจะสร้างขึ้นมาใหม่แทน
Provider ทำหน้าที่จัดหาข้อมูลที่ใช้สำหรับสร้าง Dependency ให้แก่ Injector
ถ้าเราไม่ประกาศ Service ไว้ Provider & Injector จะไม่สามารถสร้าง Service ได้เนื่องจากไม่มีข้อมูลในการสร้าง
ตัวอย่าง Provider
@Injectable
- ใส่ไว้เหนือ class เป็นการบอก Injector ว่า Class นี้สามารถนำไปสร้างเป็น Service ได้
provideIn : ‘root’ คืออะไร?
provideIn คือการระบุว่า Service นี้ Module ไหนนำไปใช้งานได้บ้าง Root แปลว่าทุก Module สามารถใช้งานได้
@NgModule
- ใส่ไว้ใน provinders ของ NgModule แปลว่าจะใช้ได้เฉพาะ Module นี้
@Component
- ใส่ไว้ใน provider ของ component แปลว่าสามารถใช้ได้แค่ภายใน Component นี้เท่านั้น หรือประกาศไว้ใน Constructor() ของ Component
- * เลือกใช้แค่แบบใดแบบหนึ่ง **
Sharing Data Between Component
เป็นการส่งข้อมูลระหว่าง Component
Input Directive
@Input
การส่งค่าจาก Parent ไปยัง Child Component
// Child ฝั่งลูกต้องประกาศ @Input รอรับตัวแปรที่แม่จะส่งมาให้
@Input('var') var:type//Parent
<app-child [var]="value"></app-child>
ฝั่งแม่ ส่งค่าให้ลูกผ่าน property บน HTML
@Output
การส่งค่าจาก Child กลับไปยัง Parent Component จะใช้การ emit (ตะโกนออกไปบอกคนข้างนอก)
//Child
@Output() output = new EventEmiiter<type>()
this.output.emit( .... )//Parent
<app-child (output)="result($event)" ></app-child>
Child Component ไม่สามารถระบุเฉพาะเจาะจงได้ว่าจะส่งค่ากลับไปให้แม่คนไหนกันแน่ (เพราะใครๆ ก็สามารถนำไปใช้ได้) ดังนั้นจึงจำเป็นต้องสร้าง Event ขึ้นมาเพื่อบอกว่าต้องการส่งข้อมูลออกไปนอก Component ตัวเอง
แล้ว Parent ที่ต้องการรับข้อมูลนั้น ให้สร้าง Function มารับค่าจาก Event นั้นเอา
Local Variable
- เข้าถึง Public Property & Function ใน Child Component โดยการสร้าง Local Variable ขึ้นมา (ขึ้นต้นด้วย #…)
//Child TS
export class ChildComponent{
private title:string = 'Get Out'
public msg:string = 'Hello'
}//Parent HTML
<app-child #child></app-child><div>{{child.msg}}</div> // ใช้งานได้
<div>{{child.title}}</div> // error ไม่สามารถเข้าถึง private บนchildได้
ViewChild
- ใช้ @ViewChild ในการเข้าถึงข้อมูล Public บน Child Component
//Child
export class ChildComponent{
public print(){
console.log('hello')
}
}//Parent HTML
<app-child #child></app-child>//Parent TS
export class ParentComponent{
@ViewChild('child') childCom: ChildComponent ngOnit(){
this.childCom.print() //hello
}}