ซีรีย์ 7 ตอน Let’s Angular ดำเนินมาถึงตอนที่ 6 แล้ว

ตอนนี้ น่าจะเป็นตอนที่สำคัญมากๆอีกหนึ่งตอน เพราะจะเป็นตอนที่ทำให้ Tour of Heroes เปลี่ยนไปเป็น SPA application จริงๆ เพราะเราจะเริ่มให้มันสามารถเปลี่ยน url ได้ เปลี่ยน page ไปมาๆ ทำให้เวปไซท์ dynamic มากขึ้น ไม่ใช่เวปที่มีหน้าเดียวอีกต่อไป

What is SPA?

หลายๆคน อาจจะงงๆว่า SPA คืออะไร??

SPA หรือ Single-Page Application เป็นรูปแบบการเขียนเวป โดยใช้แค่ view เดียว ในการแสดงผล เมื่อมีการเปลี่ยน url จะสั่งให้ js จัดการขอข้อมูล html จาก server เพื่ออัพเดต โดยไม่มีการ refresh

ดังนั้น SPA จึงถือเป็นจุดสูงสุดของการเขียน web application ด้วย js เลยทีเดียว เพราะเราสามารถคุมทุกอย่างได้โดยใช้ js และแน่นอนว่า โค้ดทั้งหมดจะรันที่ฝั่ง client ทำให้มีปัญหาหลายๆประการ โดยเฉพาะในแง่ของ security

กลับมาที่ Tour of Heroes

สิ่งที่จะเพิ่มเติมในตอนที่ 6 นี้ ประกอบไปด้วย

* เพิ่มหน้า Dashboard

* เพิ่ม navigate ระหว่างหน้า Heroes และ Dashboard

* เมื่อกดที่ชื่อของฮีโร่ จะสามารถเข้าไปยังหน้า Detail ได้

หรือ ดูได้จาก diagram

Action plan

ก่อนดำเนินการใหญ่ การวางแผนก็เป็นเรื่องสำคัญ แผนที่เรากำลังจะทำจะมีดังนี้

* ย้ายลอจิกต่างๆออกจาก AppComponent ให้เหลือเพียงลอจิกในการเปลี่ยนหน้า เพียงอย่างเดียว

* ย้าย Heros ไปอยู่ใน component ใหม่ที่ชื่อว่า HeroesComponent

* สร้าง routing สำหรับการเปลี่ยนเพจ

* สร้าง DashboardComponent ที่เป็นเพจใหม่

* เชื่อมต่อทุกอย่างเข้าด้วยกัน

ทุกอย่างก็ไม่ได้ยากอย่างที่คิด ลุย~

Splitting the AppComponent

พิจารณาสภาพแอพในปัจจุบัน จะพบว่าทุกๆครั้งที่เปิดแอพขึ้นมา angular จะทำการ load AppComponent และแสดงลิสฮีโร่ขึ้นมาโดยทันที แต่เป้าหมายของเราต้องการให้หน้าแรก แสดงตัวเลือกระหว่างหน้า “Dashboard” และ “Heros” และแสดง “Dashboard” เป็นค่าเริ่มต้น

สิ่งที่ง่ายที่สุดสำหรับการแยก “Heros” ออกมา คือ การเปลี่ยน AppComponent ไปเป็น HerosComponent แล้วค่อยสร้าง AppComponent ขึ้นมาใหม่

โดยมีขั้นตอนดังนี้

* เปลี่ยนชื่อไฟล์ app.component.ts ไปเป็น heroes.component.ts
* เปลี่ยนชื่อคลาส AppComponent ไปเป็น HeroesComponent
* และสุดท้าย คือ เปลี่ยน selector จาก my-app ไปเป็น my-heroes

Create AppComponent

และ step ต่อมา แน่นอนว่า ก็ต้องเป็นการสร้าง AppComponent ขึ้นมาแทนที่ของเก่าที่สาบสูญไป แน่นอนว่า เริ่มต้นด้วยการสร้าง app.component.ts แล้วนิยามเหมือนกับ component ปกติที่เราพูดถึงกันไปแล้วใน EP.3

แต่ที่เพิ่มเติม คือ การย้าย title จาก AppComponent เดิม (ตอนนี้คือ HeroesComponent) กลับมา และเพิ่ม <my-heroes> เพื่อให้มันแสดงผล HeroesComponent เหมือนเดิม

และท้ายที่สุด คือ ประกาศ HeroesComponent ใน AppModule เพื่อให้ angular รู้จัก <my-heroes> และเพิ่ม HeroService เข้าไปใน providers เพื่อใช้ในโอกาสต่อๆไป

หลังจากนั้น เราก็กลับไปดู app กันอีกครั้ง จะเห็นหน้าจอสดใสเหมือนเดิมไม่เปลี่ยนแปลง //ถ้ามันไม่เหมือนเดิม แน่นอนว่า เอ็งทำอะไรบางอย่างผิดแน่นอน RIP

Add routing

ภารกิจอันหนักอึ้ง ต่อมา คือการทำ routing หลายคนอาจจะสงสัยว่ามัน คืออะไร? มันสามารถอธิบายง่ายๆว่า มันคือลอจิกในการติดสินใจแสดงผลข้อมูลที่ให้ตรงกันกับ url หรือ data ที่มี โดยปกติแล้วลอจิกส่วนนี้มักอยู่ในส่วนของ server

แต่ angular สร้าง NgModule ทำให้เราสามารถจัดการลอจิกตรงนี้ได้ โดยใช้แค่ js(แต่เราเขียนด้วย ts นะ)

ก่อนจะกำหนด router เราจึงจำเป็นต้อง include RouterModule ซึ่งเป็น package รวม providers หลายๆตัวที่จะเป็นตัวช่วยในการสร้าง routing

การใช้ RouterModule จะช่วยให้เราเพิ่มความสามารถในการ navigate(คลิกเปลี่ยนเพจไปมาๆ) ได้ง่ายขึ้น โดยใช้แค่ js และไม่ต้อง refresh browser แต่อย่างไรก็ตาม ก็ย่อมมีข้อเสียตามมา เพราะว่า สิ่งที่ RouterModule จัดการเป็นสิ่งที่เรียกว่า “in-app URL” ที่ใช้ฟีเจอร์ “pushState” ที่มาใน browser ใหม่ๆ ซึ่งแน่นอนว่ามันไม่ใช่ “server URL” แบบที่เราใช้กันแบบปกติ ทำให้ application ส่วนใหญ่จำเป็นต้องเลือกแบบใดแบบหนึ่ง ระหว่างการ routing บน server หรือ ใช้ angular

และนอกจากนี้ การใช้ “in-app URL” จำเป็นต้องมีการกำหนด <base> ใน index.html เพื่อใช้ในการอ้างอิง url ต่างๆที่ใช้ผ่าน RouterModule

หลังจากรู้จัก <base> ก็มาเริ่มกำหนด route ในไฟล์ “app.module.ts” โดยการนิยาม path ที่ต้องการ ดังนี้

ในกรณีนี้ คือ สร้าง “/heroes” แล้วสั่งให้มันแสดงผลที่มาจาก HeroesComponent

** RouterModule.forRoot([..]) คือ การนิยาม path ที่เริ่มต้นจาก “/” (มั้งนะ ไว้ว่างๆจะเข้าไปศึกษาเพิ่มเติมอีกที)

แต่แค่นิยาม route อย่างเดียวมันไม่พอ เพราะว่า RouterModule ไม่รู้ว่าจะให้แสดงผลที่ไหน ดังนั้นเราจึงต้องสร้าง พื้นที่ในการแสดงผลให้มันผ่าน <router-outlet>

และท้ายที่สุด คือ เพิ่ม routerLink ไว้ภายใน AppComponent เพื่อให้มันสามารถเปลี่ยนเพจไปยัง “/heroes” ได้

และแน่นอนว่า ทุกคนยังคงสามารถใช้ <a href=”..” > ได้เหมือนเดิม แต่สิ่งมันจะไม่สามารถใช้ประโยชน์จาก “in-app URL” ได้อย่างเต็มที่ มันอาจจะทำให้เกิดการ refresh browser โดยไม่มีประโยชน์ เพราะการใช้ href ก็ไม่ต่างจาการบังคับ redirect โดยไม่ผ่าน angular

** แต่ angular1 จะจัดการ routing ผ่าน angular ให้อัตโนมัติ(ถ้าเปิดใช้ angular-router) แม้ว่าจะเป็นการใช้ href ก็ตาม

บางครั้งเราจะเรียก component ที่ทำงานแบบนี้ว่า “router component”

Add a dashboard

ต่อมา เพื่อใช้ประโยชน์จาก router อย่างเต็มที่ เราจะเริ่มสร้าง 2nd view ที่ชื่อว่า “Dashboard” โดยจัดการโดยใช้ DashboardComponent

จากนั้นก็เพิ่ม DashboardComponent เข้าไปใน AppModule แล้วกำหนด route ให้กับ DashboardComponent

และต่อมา คือ กำหนด default url ให้ลิงค์มาที่ “/dashboard”

และท้ายที่สุด คือ เพิ่ม link ที่ AppComponent เพื่อให้เราสามารถ กดลิงค์ไปมาๆระหว่างแต่ละหน้าได้

เพียงเท่านี้ เราก็ได้ app ง่ายๆที่มี 2 view สามารถกดไปมาๆได้ ฮูเร่~

แต่งานของเรายังไม่จบเพียงเท่านี้ เพราะเรายังมีงานที่ต้องสร้าง dashboard ให้เป็นรูปเป็นร่าง ไม่ใช่หน้าว่างๆแบบนี้

Add heroes to the dashboard

เริ่มต้นด้วยการใส่ templateUrl ไปยังส่วนที่เป็น @Component เพื่อแทนที่ template เดิม แล้วใส่ไฟล์ใหม่ ‘./dashboard.component.html’ ลงไป

วิธีนี้ ก็วิธีที่ใช้ในการแยก html ออกจาก js ไม่ให้มันมาเกะกะสายตาระหว่าที่เรากำลังเขียนลอจิกใน component

จากนั้นก็สร้างไฟล์ dashboard.component.html นี้ขึ้นมา โดยมีกำหนดให้มีโครงสร้างแบบที่เราออกแบบไว้ คือ แสดงรายการฮีโร่ 4 อันดับแรกสุด

แต่นั้นแปลว่า เราต้องมีตัวแปร heroes ภายใน DashboardComponent และแน่นอนว่า มันต้องเป็นค่าที่เรียกมาจาก HeroService ที่เราสร้างไว้ใน EP.5

ดังนั้น เราจึงจำเป็นต้องทำ dependency injection เพื่อเรียก HeroService มาใช้ แต่เพราะว่าเรากำหนด HeroService ไว้ใน provider ที่ AppModule ไว้เป็นที่เรียบร้อยแล้ว เสมือนเป็นการประกาศให้ HeroService เป็น Global service ที่สามารถ inject ไปได้ในทุกๆ component

เริ่มทำการ inject HeroService ใส่ลงไปใน DashboardComponent แล้วดึงค่าไปใส่ที่ตัวแปร heroes
** อ่านเพิ่มเติมที่ EP.5 ได้เลยนะ

เท่านี้ เราก็ได้ทำตามแผนที่วางไว้ครบหมดแล้ว ต่อจากนี้ไปจะเป็นส่วนเก็บรายละเอียดเพิ่มเติม เพื่อเสริมสร้าง UX ที่ดี

แต่กลัวว่าบล๊อคนี้จะยาวเกินไปขอตัดส่วนของส่วนที่เหลือไปเป็น EP6-2. Routing II ติดตามต่อในบล๊อคหน้านะ (- /\ -)//

PS.

เนื้อหาทั้งหมด จะแบ่งเป็น 7 ตอน
EP1. introduction
EP2. The Hero Editor
EP3. Master/Detail
EP4. Multiple Components
EP5. Services
EP6. Routing
EP7. HTTP
ตามดูโค้ดได้ที่ Github

Thank you

Angular.io บทความนี้อยู่ภายใต้ลิขสิทธิ์แบบ CC BY 4.0

Tell your friend about thisShare on Facebook
Facebook
0Tweet about this on Twitter
Twitter
Share on Google+
Google+
0