Jquery ว ธ แก ใขข อม ลในคลาสเด ม

CHAPTER 13 การพัฒนา Web Apps แบบ MEAN Stack ขัน้ ตน้ ÂÂ เมอ่ื มกี ารรอ้ งขอใดๆ กต็ ามเขา้ มา สง่ั ใหไ้ ฟลท์ ช่ี อ่ื วา่ index.html ท�ำ งานเปน็ ล�ำ ดบั แรก server.js 1 app.use(‘*’, function(req, res){ 2 res.sendFile(path.join(__dirname, ‘index.html’)); 3 }) ค�ำ ถามกค็ ือ โฟลเดอร์ dist และไฟล์ index.html มาจากไหน ใครเป็นผู้สรา้ ง การส่งั รนั โปรเจ็กต์ MEAN Stack โครงสร้างโปรเจก็ ต์ Angular ปัจจบุ ัน ประกอบด้วย 2 ส่วน ดังน้ี ÂÂ โปรเจ็กต์ Angular เดิม ทำ�หน้าที่สร้างส่วนแสดงผลที่เกิดจากคอมโปเนนท์ต่างๆ ประกอบเขา้ ดว้ ยกัน ÂÂ โปรเจก็ ต์ express ทำ�หนา้ ท่ีฝ่ัง Server 1. เราต้องการใชง้ านสว่ นแสดงผล (Output) ทีไ่ ด้มาจากโปรเจก็ ต์ Angular ใหพ้ มิ พ์ คำ�สง่ั ng build เพอื่ สร้างไฟล์ต่างๆ ในโฟลเดอรท์ ช่ี อ่ื ว่า dist กอ่ น ดังรูปที่ 13-5 Angular CLI Command Prompt 1 ng build รปู ที่ 13-5 แสดงไฟล์ Output ทไี่ ดจ้ ากโปรเจก็ ต์ Angular จากรูปที่ 13-5 รายการไฟล์ต่างๆ เหล่านี้ ถูกสร้างขึ้นมาจากโปรเจ็กต์ Angular ใน กรณที ่โี ปรเจ็กต์ Angular มกี ารเปล่ียนแปลงหรอื แกไ้ ข เราต้องสั่ง ng build ใหมเ่ สมอ เพือ่ ใหไ้ ด้สว่ นแสดงผลลา่ สดุ นน่ั เอง ScJraivpat 245

สง่ ผลให้รายการไฟลส์ ่วนแสดงผลทีอ่ ยู่ในโฟลเดอร์ dist พรอ้ มใชง้ านแลว้ 2. ต่อมา เราจะส่ังให้ express ทำ�งาน โดยการพิมพ์คำ�สั่ง node server เพื่อสั่งให้ ไฟล์ server.js ทำ�งาน ดังรปู ที่ 13-6 Command Prompt 1 node server รปู ท ี่ 13-6 แสดงการส่ังให้ express ทำ�งาน จากรูปที่ 13-6 express พร้อมทำ�งานทพี่ อรต์ 3000 แลว้ 3. การทำ�งานของไฟล์ server.js ทเ่ี รากำ�หนดไว้ในขณะน้ี คอื สง่ั ให้แสดงไฟล์ index.html ทอี่ ย่ใู นโฟลเดอร์ dist (ได้มาจากโปรเจ็กตข์ อง Angular) ดังรูปที่ 13-7 รปู ที่ 13-7 ส่วนแสดงผลท่ีเกิดจาก Angular (สัง่ งานผ่านทาง express) จากรูปที่ 13-7 ให้เปิดบราวเซอร์ขึ้นมา เข้าไปที่พาธ localhost:3000 (เป็นพาธของ express) กจ็ ะไดส้ ่วนแสดงผลทมี่ าจาก Angular กล่าวได้อกี นัยหนง่ึ ว่า โปรเจก็ ต์ Angular ของเราพรอ้ มทำ�งานกับ express แลว้ นน่ั เอง สคริปต์ express ของฝ่งั Server การสรา้ งโปรเจก็ ตส์ �ำ หรบั เรยี กดขู อ้ มลู หนงั สอื จากคอลเลก็ ชนั books และแสดงผลดว้ ย ไฟล์ท่ีเกิดจาก Angular เราจะเร่มิ ต้นที่ฝ่ัง express (ฝั่ง Server) กอ่ น มขี ัน้ ตอนดังน้ี 1. ท่ีไฟล์ books.js ในโฟลเดอร์ models ตอ้ งก�ำ หนดก่อนว่าโครงสรา้ งข้อมลู หนังสือที่ เราสนใจ มีอะไรบา้ ง ในกรณีนคี้ อื hh รหสั isbn กำ�หนดให้มชี นิดขอ้ มลู ขอ้ ความ string hh ช่ือหนงั สอื title ก�ำ หนดให้มชี นิดข้อมูลข้อความ string hh ราคาหนังสือ price กำ�หนดให้มชี นดิ ขอ้ มลู ตัวเลข number 246

CHAPTER 13 การพฒั นา Web Apps แบบ MEAN Stack ขนั้ ตน้ สครปิ ต์ JavaScript ท่ี 13-1 การพัฒนา Web Apps แบบ MEAN Stack ขน้ั ตน้ (\\models\\books.js) 1 var mongoose = require(‘mongoose’); 2 var Schema = mongoose.Schema; 3 4 var BooksSchema = new Schema({ 5 isbn: String, 6 title: String, 7 price: Number 8 }); 9 10 module.exports = mongoose.model(‘books’, BooksSchema); รปู ท ่ี 13-8 แสดงโครงสร้าง ข้อมูลหนงั สือทเ่ี ราสนใจ 2. ตอ่ มา ท่ีไฟล์ api.js ในโฟลเดอร์ server กำ�หนดให้มีช่องทางเรียกดขู ้อมลู หนงั สือ ทั้งหมดแบบไมม่ เี งือ่ นไขเพยี งอยา่ งเดยี ว ดังสคริปตต์ อ่ ไปน้ี สครปิ ต์ JavaScript ที่ 13-1 การพัฒนา Web Apps แบบ MEAN Stack ขัน้ ต้น (\\server\\api.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 var Book = require(‘../models/Book.js’); 4 5 router.get(‘/’, function(req, res) { 6 Book.find(function (err, dbBooks) { 7 res.json(dbBooks); 8 }); 9 }); 10 11 module.exports = router; จากสครปิ ตข์ า้ งตน้ การท�ำ งานของฝงั่ express เหลอื เพยี งแคท่ �ำ งานกบั สว่ นของขอ้ มลู ที่ อยใู่ นฐานขอ้ มูล Mongo อยา่ งเดยี วเท่านัน้ ในกรณนี ีค้ อื เรยี กดขู ้อมูลหนงั สือท้ังหมดแบบไมม่ ี เง่อื นไข สว่ นการจดั การดา้ นแสดงผลยกให้เป็นหน้าทขี่ อง Angular ทัง้ หมด ScJraivpat 247

3. ต่อมา ทไี่ ฟล์ server.js ทำ�หน้าทส่ี ั่งให้ express ท�ำ งาน ดังสคริปต์ตอ่ ไปน้ี สคริปต์ JavaScript ท่ี 13-1 การพฒั นา Web Apps แบบ MEAN Stack ขน้ั ตน้ (server.js) 1 var express = require(‘express’); 2 var path = require(‘path’); 3 var bodyParser = require(‘body-parser’); 4 var mongoose = require(‘mongoose’); 5 6 mongoose.connect(‘mongodb://localhost/myshops’); 7 8 var api = require(‘./server/api’); 9 var app = express(); 10 11 app.use(bodyParser.json()); 12 app.use(bodyParser.urlencoded({ extended: false })); 13 app.use(express.static(path.join(__dirname, ‘dist’))); 14 13 app.use(‘/api’, api); 14 15 var server = app.listen(3000, function() { 16 var port = server.address().port; 17 console.log(‘Server is running... %s’, port); 18 }) ณ จดุ นี้ สคริปตข์ อง express (ฝ่ัง Server) ครบถ้วนแล้ว ก�ำ หนดใหเ้ มอ่ื มีการรอ้ งขอ้ มูล มาทพี่ าธ /api ท�ำ หนา้ ทแ่ี สดงขอ้ มูลหนังสอื ทงั้ หมดแบบไมม่ ีเงอ่ื นไข การสรา้ งเซอรว์ ิส (Service) ใน Angular โปรเจ็กต์ Angular ปัจจุบัน ผู้เขียนต้องการให้คอมโปเนนท์ที่ช่ือว่า app-book ท�ำหน้าท่ีแสดงข้อมูลที่ได้จาก express แต่การน�ำข้อมูลจากฝั่ง express (ถือเป็นฝั่ง Server) มาใช้งาน เราไม่ได้น�ำคอมโปเนนท์ไปเรียกดูโดยตรง เหตุผลก็เพราะเราต้องไม่ลืมว่าใน โปรเจ็กต์ Angular ยอ่ มทจ่ี ะต้องประกอบไปดว้ ยคอมโปเนนทต์ ่างๆ มากมาย ถา้ เราก�ำหนด ให้ส่วนของข้อมูลไปฝังไว้ในคอมโปเนนท์ตัวใดตัวหน่ึง ก็จะท�ำให้คอมโปเนนท์ตัวอื่นๆ ไม่สามารถท�ำงานกบั ขอ้ มลู ฝัง่ Server ไดเ้ ลย ตอ้ งเขยี นการท�ำงานส่วนน้ี ซ�้ำไป-มาตลอดเวลา ถอื เปน็ การท�ำงานทไี่ มด่ ีเท่าใดนกั การท�ำ งานกบั สว่ นของข้อมลู ใน Angular เราจะอาศยั เซอร์วสิ (Service) เขา้ มารบั ผดิ ชอบงานด้านน้ี หวั ใจหลกั ของเซอรว์ ิสใน Angular กค็ อื ถอื เปน็ บรกิ ารสว่ นกลาง คอมโปเนนท์ ไหนอยากใชบ้ รกิ ารดา้ นใดกเ็ ลอื กใช้ไดต้ ามความต้องการ 248

CHAPTER 13 การพฒั นา Web Apps แบบ MEAN Stack ขั้นตน้ ถา้ เราจะวางต�ำ แหน่งระหวา่ งเซอรว์ ิสกบั คอมโปเนนท์ กจ็ ะไดป้ ระมาณว่า ÂÂ เซอรว์ สิ ท�ำ หนา้ ทีบ่ ริการดา้ นต่างๆ เช่น บรกิ ารให้ข้อมูลหนังสือทงั้ หมด เป็นตน้ ÂÂ คอมโปเนนท์ ท�ำ หนา้ ทแ่ี สดงขอ้ มูลจากเซอร์วิสทีเ่ ราสนใจอยู่ การใชง้ านเซอร์วิสในโปรเจก็ ต์ Angular มขี ้นั ตอนดงั น้ี 1. ให้พิมพค์ ำ�สงั่ ตอ่ ไปน้ี เพ่อื สร้างเซอรว์ สิ ทช่ี อื่ วา่ BookService Angular CLI Command Prompt 1 ng g service Book รูปท่ี 13-9 แสดงการสรา้ งเซอรว์ สิ ทชี่ อื่ วา่ BookService จากรูปท่ี 13-9 เหน็ ไดว้ ่าสครปิ ตข์ องเซอร์วสิ ใชร้ ะบบคลาสของภาษา TypeScript เช่น เดียวกับคอมโปเนนท์ คำ�ถามก็คือ ความแตกต่างระหว่างเซอร์วิสกับคอมโปเนนท์ คืออะไร ผเู้ ขยี นขอใหย้ ึดหลกั วา่ ÂÂ เซอรว์ สิ คือ คลาสทีไ่ มม่ สี ว่ นแสดงผล ÂÂ คอมโปเนนท์ คือ คลาสที่มีส่วนแสดงผล แบ่งแยกระหว่างตัวข้อมูลกับส่วน แสดงผลออกจากกันอย่างเด็ดขาด 2. ตอ่ มา เซอรว์ สิ BookService ที่ถูกเพิ่มเข้ามาใหม่ ถ้า ต้องการใช้งานโปรเจ็กต์ ปจั จบุ นั กต็ อ้ งอา้ งองิ ในไฟล์ app.module.ts ใหค้ รบถว้ น ก่อน กลา่ วคอื รูปที ่ 13-10 แสดงการอา้ งองิ เซอรว์ สิ BookService ในไฟล์ app.module.ts ScJraivpat 249

ÂÂ อ้างอิงไลบรารี่สำ�หรบั ร้องขอขอ้ มูลผ่านทางโปรโตคอล HTTP ÂÂ อา้ งอิงตัวเซอร์วิส BookService \\src\\app\\components\\app.module.ts 1 import { HttpClientModule } from ‘@angular/common/http’; 2 import { BookService} from ‘./book.service’; ประกาศใช้ไลบราร่ี HttpClientModule ท่สี ว่ น imports ÂÂ ประกาศใช้เซอรว์ สิ BookService ท่สี ว่ น providers \\src\\app\\components\\app.module.ts 1 @NgModule({ 2 declarations: [ 3 AppComponent, 4 BookComponent, 5 FooterComponent 6 ], 7 imports: [ 8 BrowserModule, 9 FormsModule, 10 HttpClientModule 11 ], 12 providers: [BookService], 13 bootstrap: [AppComponent] 14 }) 3. เราทราบมาก่อนหน้านี้ แล้วว่า ถ้าต้องการข้อมูล หนังสือท้ังหมดแบบไม่มี เงอื่ นไข ใหร้ อ้ งขอไปทพี่ าธ /api ดังสคริปตต์ อ่ ไปน้ี รูปท่ี 13-11 แสดงสคริปต์ใน เซอรว์ สิ BookService จากรปู ท่ี 13-11 เซอรว์ ิส BookService พร้อมให้บรกิ ารข้อมลู หนังสอื ท้งั หมดแบบไม่มี เงอื่ นไขแลว้ คอมโปเนนท์ใดสนใจขอ้ มลู นีเ้ รียกใช้ผา่ นทางฟงั กช์ นั ที่ช่อื ว่า getBooks() 250

CHAPTER 13 การพัฒนา Web Apps แบบ MEAN Stack ขน้ั ตน้ 4. ในโปรเจก็ ต์Angular ปจั จบุ นั เรามคี อมโปเนนทท์ ช่ี อ่ื วา่ app-book อยแู่ ลว้ ผเู้ ขยี น ต้องการให้คอมโปเนนท์ตัวนี้ทำ�หน้าที่แสดงข้อมูลหนังสือทั้งหมดแบบไม่มีเง่ือนไข จึงเรยี กใช้เซอรว์ สิ BookService ดงั สครปิ ต์ต่อไปนี้ สคริปต์ TypeScript ท่ี 13-1 การพัฒนา Web Apps แบบ MEAN Stack ขน้ั ตน้ (\\src\\components\\book\\book.component.ts) 1 import { Component, OnInit } from ‘@angular/core’; 2 import { BookService} from ‘../../book.service’; 3 4 @Component({ 5 selector: ‘app-book’, 6 templateUrl: ‘./book.component.html’, 7 styleUrls: [‘./book.component.css’] 8 }) 9 export class BookComponent implements OnInit { 10 result: any; 11 12 constructor(private _bookService: BookService) { } 13 14 ngOnInit() { 15 this.getAllBooks(); 16 } 17 18 getAllBooks() { 19 this._bookService.getBooks().then(data => { 20 this.result = data; 21 }, err => { 22 console.log(err); 23 }); 24 } 25 } รูปท ่ี 13-12 แสดงคอมโปเนนท์ app- book เรยี กใชเ้ ซอรว์ สิ BookService ScJraivpat 251

5. ตอ่ มา ทไ่ี ฟลส์ ว่ นแสดงผลbook.component.html ก�ำ หนดใหแ้ สดงรายการหนงั สอื ทั้งหมดในรูปแบบของตาราง HTML ดงั สคริปต์ต่อไปน้ี สครปิ ต์ TypeScript ที่ 13-1 การพัฒนา Web Apps แบบ MEAN Stack ขั้นตน้ (\\src\\components\\book\\book.component.html) 1

รายการหนงั สอื

2 3 4 5 6 7 8 9 10 11
รหสั ISBNชื่อหนงั สือราคา
{{ item.isbn }}{{ item.title }}{{ item.price }}
รปู ที่ 13-12 สคริปต์ส่วนแสดงผล ของ book.component.html 6. ให้ทดสอบรันโปรเจ็กต์ โดยการพิมพ์คำ�สง่ั ng build เพื่อสรา้ งสว่ นแสดงผลล่าสุด จากโปรเจ็กต์ Angular ก่อน ในกรณีที่ส่วนแสดงผลของเราไม่มีการเปล่ียนแปลง ไมต่ ้องสรา้ งใหมก่ ไ็ ด้ รปู ที่ 13-14 แสดงการ build โปรเจก็ ต์ Angular ใหม่ 252

CHAPTER 13 การพัฒนา Web Apps แบบ MEAN Stack ข้นั ตน้ 7. ต่อมา ให้พิมพค์ ำ�สัง่ node server เพ่ือส่งั ให้ express (ฝง่ั Server) ทำ�งาน ดงั รูป ท่ี 13-15 รูปท่ี 13-15 ฝ่งั express พรอ้ มทำ�งานแล้ว 8. ทา้ ยทส่ี ดุ ใหเ้ ปดิ บราวเซอร์ แลว้ ไปทพ่ี าธ localhost:3000 ซ่ึงเป็นของ express ก็จะพบกับรายการหนังสือแสดงใน รปู แบบตาราง ดงั รูปท่ี 13-16 รปู ท ่ี 13-16 ผลการรนั ตัวอย่างท่ี 13-1 จากรูปที่ 13-16 รายการหนงั สอื ทเ่ี หน็ ประกอบไปด้วย ÂÂ ส่วนแสดงผลท่ไี ด้มาจาก Angular (หนา้ บา้ น) ÂÂ เรียกดูขอ้ มลู ผา่ น express เชื่อมตอ่ ไปทฐี่ านข้อมลู Mongo (หลงั บ้าน) อธิบายการท�ำ งานของสคริปต์ 1. เรม่ิ ต้นทฝี่ ่งั express กอ่ น ในไฟล์ server.js สงั่ ใหเ้ ช่อื มต่อกับฐานขอ้ มลู myshops โดยอาศัย mongoose server.js 1 var express = require(‘express’); 2 var path = require(‘path’); 3 var bodyParser = require(‘body-parser’); 4 var mongoose = require(‘mongoose’); 5 6 mongoose.connect(‘mongodb://localhost/myshops’); 2. ตอ่ มา สรา้ งตวั แปรท่ีช่อื วา่ api ทำ�หน้าทแ่ี ทนไฟล์ api.js ที่อย่ใู นโฟลเดอร์ server ในกรณที ี่มีการร้องขอมาท่ีพาธ /api กจ็ ะส่ังใหไ้ ฟล์ api.js ท�ำ งาน ScJraivpat 253

server.js 1 var api = require(‘./server/api’); 2 ... 3 ... 4 ... 5 app.use(‘/api’, api); 3. ตอ่ มา ผเู้ ขยี นก�ำ หนดใหไ้ ฟล์api.js มกี ารท�ำ งานเพยี งอยา่ งเดยี ว นน่ั คอื การแสดงขอ้ มลู หนงั สอื ทง้ั หมดแบบไมม่ เี งอื่ นไข ทสี่ �ำ คญั กค็ อื ก�ำ หนดขอ้ มลู หนงั สอื ทไ่ี ดม้ าใหอ้ ยใู่ น รูปแบบ JSON (res.json(dbBooks)) กลา่ วได้อกี นัยหนง่ึ วา่ น่คี อื ชอ่ งทางท่ฝี ั่ง Server เปดิ ไว้ให้กบั ฝ่งั Client สามารถเรยี กดู ขอ้ มลู โดยการร้องขอมาทีพ่ าธ /api \\server\\api.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 var Book = require(‘../models/Book.js’); 4 5 router.get(‘/’, function(req, res) { 6 Book.find(function (err, dbBooks) { 7 res.json(dbBooks); 8 }); 9 }); 4. ตอ่ มา การรอ้ งขอขอ้ มลู จากฝ่ัง Server ของ Angular ตอ้ งสร้างเซอรว์ ิสขึ้นมากอ่ น ตง้ั ช่ือวา่ BookService มหี น้าที่ร้องขอข้อมูลผ่านทางโปรโตคอล HTTP จึงตอ้ งมกี าร อ้างองิ @angular/common/http ตัง้ ชอ่ื ว่า HttpClient \\src\\app\\book.service.ts 1 import { Injectable } from ‘@angular/core’; 2 import { HttpClient } from ‘@angular/common/http’; 5. ตอ่ มา การท�ำ งานภายในคลาส BookService โดยใหส้ รา้ งพารามเิ ตอรท์ ช่ี อ่ื วา่ _http ก�ำ หนดใหม้ ชี นิดขอ้ มูลเป็น HttpClient ขนึ้ มากอ่ น 254

CHAPTER 13 การพัฒนา Web Apps แบบ MEAN Stack ข้นั ตน้ \\src\\app\\book.service.ts 1 @Injectable() 2 export class BookService { 3 4 constructor(private _http: HttpClient) {} 6. ตอ่ มา ผเู้ ขียนสร้างฟังกช์ นั ทช่ี ่อื ว่า getBooks() ขึ้นมาในคลาส BookService มหี นา้ ที่ แสดงข้อมลู หนงั สอื ทงั้ หมดแบบไม่มเี งอ่ื นไขเพียงอย่างเดยี ว การท�ำ งานภายในฟังก์ชนั นีก้ อ็ าศยั ฟงั ก์ชนั get() ของพารามิเตอร์ _http รอ้ งขอขอ้ มูล ไปที่พาธเป้าหมาย /api \\src\\app\\book.service.ts 1 getBooks() { 2 return this._http.get(‘/api’).toPromise(); 3} 4} กลา่ วได้อกี นยั หนงึ่ ว่า ถ้าเราต้องการข้อมลู หนังสือทัง้ หมดแบบไมม่ เี งอื่ นไข ใหเ้ รียกใช้ ฟงั กช์ นั getBooks() ของเซอรว์ สิ BookService นน่ั เอง และถอื วา่ บรกิ ารขอ้ มลู BookService น้ี เป็นบริการส่วนกลางภายในโปรเจ็กต์ Angular คอมโปเนนท์ใดก็ตามท่ีสนใจ สามารถเรียก ใชง้ านได้อยา่ งอสิ ระ 7. ต่อมา ผู้เขียนต้องการให้คอมโปเนนท์ app-book ทำ�หน้าท่ีแสดงข้อมูลหนังสือ จงึ ตอ้ งเรียกใชเ้ ซอรว์ ิส BookService ประเด็นที่น่าสนใจก็คือ วิธีการเรียก ใช้เซอร์วิส BookService ในคอมโปเนนท์ app-book ทำ�อย่างไร ให้ดูรูปท่ี 13-17 ประกอบค�ำ อธิบาย รปู ท่ี 13-17 ลำ�ดับชั้นของไฟล์ book.service.ts กับ book.component.ts ScJraivpat 255

ÂÂ ผ้ใู ห้บรกิ าร เซอร์วสิ book.service.ts อยู่ในโฟลเดอรย์ ่อย \\src\\app ÂÂ ผู้เรียกใช้บริการ คอมโปเนนท์ book.component.ts อยู่ในโฟลเดอร์ย่อย \\src\\ app\\components\\book เห็นได้ว่าคอมโปเนนท์ app-book (ผู้เรียกใช้บริการ) อยู่ในระดับลึกกว่าเซอร์วิส BookService (ผู้ให้บริการ) จ�ำ นวน 2 ระดับช้นั โฟลเดอร์ย่อย วิธีการอ้างอิงโดยเราต้องทำ�ให้คอมโปเนนท์ app-book อยู่ในระดับเดียวกับเซอร์วิส BookService กอ่ น โดยใช้ . . จำ�นวน 2 ครง้ั เพอื่ ให้มาอยู่ระดบั เดยี วกัน แลว้ จงึ อ้างองิ ช่ือไฟล์ /book.service (.ts) เกบ็ ไวท้ ต่ี ัวแปร BookService \\src\\app\\components\\book\\book.component.ts 1 import { Component, OnInit } from ‘@angular/core’; 2 import { BookService} from ‘../../book.service’; 8. ต่อมา คอมโปเนนท์ app-book ยังคงใช้สว่ นแสดงผลที่ชือ่ ว่า book.component. html \\src\\app\\components\\book\\book.component.ts 1 @Component({ 2 selector: ‘app-book’, 3 templateUrl: ‘./book.component.html’, 4 styleUrls: [‘./book.component.css’] 5 }) 9. ตอ่ มา ภายในคลาสBookComponent ใหส้ รา้ งตวั แปรทชี่ อื่ วา่ result ขนึ้ มา ก�ำ หนด ให้มชี นิดขอ้ มูลใดกไ็ ด้ (any) ท�ำ หน้าท่ีเกบ็ ข้อมูลทีไ่ ดม้ าจากเซอร์วิส BookService \\src\\app\\components\\book\\book.component.ts 1 export class BookComponent implements OnInit { 2 result: any; 10. ต่อมา สร้างพารามิเตอร์ที่ชื่อว่า _bookService กำ�หนดให้มีชนิดข้อมูลเป็น BookService \\src\\app\\components\\book\\book.component.ts 1 constructor(private _bookService: BookService) { } 256

CHAPTER 13 การพัฒนา Web Apps แบบ MEAN Stack ข้นั ตน้ 11. ต่อมา เพื่อให้สคริปต์ของเราเป็นระเบียบยิ่งข้ึน จึงเขียนสคริปต์ส่วนของการเรียก ดูข้อมูล แยกเก็บไว้ในฟังก์ชันต่างหาก ต้ังชื่อว่า getAllBooks() โดยการเรียกใช้ ฟังกช์ ัน getBooks() ของเซอรว์ ิส _bookService ข้อมูลหนงั สือท้ังหมดที่ไดม้ าเกบ็ อยใู่ นพารามิเตอร์ data ก็จะส่งต่อใหก้ ับตวั แปร result ท่ีเราสรา้ งไว้ก่อนหนา้ น้ีน่นั เอง \\src\\app\\components\\book\\book.component.ts 1 getAllBooks() { 2 this._bookService.getBooks().then(data => { 3 this.result = data; 12. ท้ายทส่ี ุด ทฟี่ ังก์ชัน ngOnInit() ใหเ้ รยี กใช้ฟังก์ชัน getAlBooks() อีกทอดหน่ึง ก็ จะไดข้ ้อมูลหนงั สอื ท้งั หมดเก็บอยู่ในตัวแปร result \\src\\app\\components\\book\\book.component.ts 1 ngOnInit() { 2 this.getAllBooks(); 3} 13. ที่ไฟล์ส่วนแสดงผล book.component.html ให้สร้างตารางที่มี 3 คอลัมน์ขึ้นมา กอ่ น ก�ำ หนดให้แสดงเส้นตารางผา่ นทางแอ็ตทริบิวต์ border = ‘1’ ดว้ ย \\src\\app\\components\\book\\book.component.html 1

รายการหนงั สอื

2 3 4 5 14. ตอ่ มา ขอ้ มลู ทอี่ ยใู่ นตวั แปรresult มหี ลายชดุ เราสามารถสง่ั ใหว้ นลปู เพอ่ื อา่ นขอ้ มลู หนังสือออกมาทีละเล่มโดยการใชค้ �ำ สั่ง *ngFor ในแต่ละรอบของการวนลูป ส่ังให้สร้างแถวขึ้นมาใหม่โดยอาศัยอิลีเมนต์ … ข้อมูลหนังสือแต่ละเล่มถกู เกบ็ อยูใ่ นตวั แปรทช่ี ือ่ วา่ item \\src\\app\\components\\book\\book.component.html 1 ScJraivpat 257

15. ท้ายท่ีสุด กำ�หนดให้สร้างคอลัมน์ข้ึนมา 3 ชุด โดยอาศัยอิลีเมนต์

แต่ละคอลมั น์ ให้ทำ�ดงั น้ี ÂÂ คอลัมนท์ ่ี 1 แสดงรหสั ISBN อา่ นคา่ ไดจ้ าก item.isbn ÂÂ คอลมั นท์ ี่ 2 แสดงชอื่ หนังสอื อา่ นคา่ ได้จาก item.title ÂÂ คอลัมน์ที่ 3 แสดงราคา อา่ นค่าได้จาก item.price \\src\\app\\components\\book\\book.component.html 1 2 3 4 5
รหัส ISBNช่ือหนงั สือราคา
{{ item.isbn }}{{ item.title }}{{ item.price }}
สรปุ ท้ายบท การพัฒนา Web Apps แบบ MEAN Stack ยังมีรายละเอียดอีกมากมายที่ ยังไม่ได้นำ�เสนอในหนังสือเล่มนี้ เจตนาของผู้เขียนก็เพื่อต้องการนำ�เสนอเน้ือหาให้ ครอบคลมุ หวั ข้อส�ำ คญั ๆ ของ MEAN Stack ให้มากทสี่ ุดเทา่ ทีเ่ ป็นไปได้ เพ่ือเป็นฐาน ให้ผูอ้ ่านนำ�ไปต่อยอดในลำ�ดบั ตอ่ ไป 258

Java script 14CHAPTER การใชง้ าน Angular ในโลกของ .NET Core ในปัจจุบันการพัฒนา Web Apps ในแพลตฟอร์มของ .NET Core ถือเป็นอีกเรื่องท่ีน่า สนใจและพลาดไม่ได้ เราสามารถใช้ Angular ร่วมกับ ASP.NET Core MVC ได้อีกด้วย หนา้ ท่ขี อง Angular ใน ASP.NET Core MVC การพฒั นา Web Apps ในโลกของ .NET Core จะอาศยั โปรเจก็ ตป์ ระเภท ASP.NET Core MVC โดยท่ผี ู้เขียนเลือกใชภ้ าษา C# แบง่ โครงสรา้ งของโปรเจก็ ตอ์ อกเป็น 3 สว่ น ดงั น้ี ÂÂ Model (M) หมายถึง ส่วนของขอ้ มูล อาจจะเปน็ ข้อมูลช่ัวคราวที่เก็บอยใู่ นรปู แบบ โครงสร้างข้อมลู ต่างๆ ท่ี .NET รองรบั หรือเก็บขอ้ มูลแบบถาวรในระบบฐานขอ้ มลู ÂÂ View (V) หมายถึง ส่วนแสดงผลหนา้ จอตา่ งๆ อยใู่ นไฟลน์ ามสกุล .cshtml ÂÂ Controler (C) หมายถงึ ส่วนของผู้สั่งการให้เกิดการท�ำ งานต่างๆ เช่น การเพ่มิ , แก้ไข, ลบข้อมูล, คน้ หาข้อมูล เปน็ ต้น ส่วนแสดงผลเดมิ View (V) ของโปรเจ็กต์ ASP.NET Core MVC เปน็ หน้าทข่ี องไฟลท์ ่ี มีนามสกลุ .cshtml เมอ่ื ตอ้ งการใช้ Angular ท�ำให้หน้าทก่ี ารสรา้ งแสดงผลตามหนา้ จอตา่ งๆ เปน็ ของ Angular ทง้ั หมด HTML .Net HTML

เราสามารถแบง่ หนา้ ทอี่ อกเปน็ 2 สว่ นได้ดังนี้ 1. หนา้ บา้ น หรือสว่ นแสดงผลหน้าจอต่างๆ เป็นหนา้ ทขี่ อง Angular 2. หลังบ้าน เป็นหน้าที่ของ ASP.NET Core MVC เทียบได้กับ Node + Express + MongoDB (ถ้ามกี ารใช้ระบบฐานข้อมลู ) ส�ำหรบั ผู้อ่านท่ีไมเ่ คยใช้งาน ASP.NET Core MVC มาก่อนเลย สามารถท�ำความเขา้ ใจ ไดไ้ มย่ าก เพราะถา้ เขา้ ใจหนา้ ท่ขี องแตล่ ะส่วนแลว้ กไ็ ม่เป็นปญั หาในการเรยี นรู้แต่อยา่ งใด การสร้างโปรเจก็ ต์ ASP.NET Core MVC ทีม่ ีการใชง้ าน Angular การใช้งาน Angular ร่วมกับ ASP.NET Core MVC เปน็ โปรเจก็ ต์ประเภทหนงึ่ ใน Visual Studio โครงสร้างโปรเจ็กต์ที่เราได้มามีความสมบูรณ์ในระดับหน่ึง โดยที่ไม่จ�ำเป็นต้องการ ค�ำส่ัง npm ดาวน์โหลดรายการต่างๆ ด้วยตัวเอง งานเหล่านี้ถูกสั่งให้ท�ำงานโดยอัตโนมัติ ทงั้ หมด ตวั อยา่ งท่ี 14-1 ตวั อย่างท่ี 14-1 การสรา้ งโปรเจก็ ต์ ASP.NET Core MVC ทีม่ กี ารใชง้ าน Angular มขี ้ันตอนดังน้ี 1. ที่หนา้ ต่างสร้างโปรเจก็ ตใ์ หม่ (New Project) ของ Visual Studio ทีห่ ัวขอ้ Visual C# > .NET Core สร้างโปรเจก็ ต์แบบ ASP.NET Core Web Application ตัง้ ช่ือว่า UsingAngularWithASP ดังรปู ที่ 14-1 รูปท่ ี 14-1 แสดงการสรา้ งโปรเจก็ ต์ ASP.NET Core MVC 260

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core 2. ตอ่ มา ใหส้ ร้างโปรเจ็กต์ประเภท Angular ดังรปู ท่ี 14-2 รปู ที่ 14-2 สรา้ งโปรเจ็กต์ประเภท Angular จากรูปที่ 14-2 ใหเ้ ลอื กสร้างโปรเจ็กต์ ASP.NET Core เวอรช์ ัน 2.1 ขึ้นไป 3. ตอ่ มา ให้ดทู ีห่ นา้ ตา่ ง Solution Explorer การสรา้ งโปรเจก็ ต์ ASP.NET Core MVC ที่มีการใช้งาน Angular ต้องมีการดาวน์โหลดรายการต่างๆ ก่อน ให้รอจนกว่า ไอคอนสีเหลืองหายไปจนหมด ดงั รปู ที่ 14-3 รูปที ่ 14-3 แสดงโครงสร้างโปรเจ็กต์ ASP.NET Core MVC ท่ีมีการใชง้ าน Angular ScJraivpat 261

จากรูปที่ 14-3 ผู้อ่านท่ีเคยใช้งาน ASP.NET Core MVC มาก่อน พบว่าโครงสร้าง โปรเจ็กตแ์ ตกตา่ งไปจากเดมิ พอสมควร 4. ในขน้ั ตน้ นเี้ ราไมส่ นใจหนา้ ทขี่ องแตล่ ะไฟลห์ รอื โคด้ ใดๆ ทง้ั สน้ิ เราตอ้ งการทดสอบ โปรเจก็ ตก์ อ่ นเลยวา่ มหี นา้ ตาอยา่ งไร โดยการคลกิ ทปี่ มุ่ เพอื่ ทดสอบรนั โปรเจ็กตท์ ่หี น้าแรก Home เป็นการรอ้ งขอข้อมูลแบบ Get มาทพี่ าธ /home กจ็ ะ เป็นหน้าจอแสดงตวั อยา่ งข้อมูลทว่ั ไป ดงั รปู ที่ 14-4 รปู ท่ ี 14-4 ผลการรนั ตวั อย่างท่ี 14-1 262

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core 5. ตอ่ มา ให้ลองเลอื กลิงก์ Counter รอ้ งขอข้อมลู มาทพ่ี าธ /counter เมอ่ื คลิกทป่ี มุ่ เปน็ การนับตวั เลขเพ่ิมขน้ึ ครง้ั ละ 1 ดังรูปท่ี 14-5 รูปที ่ 14-5 แสดงหนา้ จอของพาธ /counter 6. ทา้ ยทีส่ ุด ให้คลิกทลี่ งิ ก์ Fetch data รอ้ งขอข้อมูลมาทพี่ าธ /fetch-data เปน็ การ ทำ�งานร่วมกันระหว่างข้อมูลที่ได้มาจาก ASP.NET Core MVC (หลังบ้าน) นำ�มา แสดงผลในคอมโปเนนท์ของ Angular (หน้าบา้ น) เปน็ โครงสรา้ งข้อมูลหลายๆ ชุด ท่ถี กู สมุ่ ขึน้ มา ดงั รปู ท่ี 14-6 รปู ท ี่ 14-6 หน้าจอของพาธ /fetch-data ScJraivpat 263

ท�ำ ความรู้จกั กับโครงสรา้ งโปรเจ็กต์ ASP.NET Core MVC ทีม่ ีการ ใชง้ าน Angular เปา้ หมายแรกของเราก็คือ ศึกษาวธิ กี ารท�ำงานของ ASP.NET Core MVC (อยใู่ นฐานะ หลังบา้ น) ร่วมกับ Angular (อยู่ในฐานะหน้าบ้าน) อย่างไร ให้ดทู ี่ไฟล์ Startup.cs ท�ำหน้าท่ี ปรับแตง่ คา่ ตา่ งๆ ใหก้ บั โปรเจ็กต์ ASP.NET Core MVC ท่ีน่าสนใจมี 2 ประการดงั นี้ 1. app.UseSpaStaticFiles() หมายถึง กำ�หนดให้โปรเจ็กต์ ASP.NET Core MVC ใช้ งานไฟล์ประเภท Static ดว้ ย เชน่ ไฟล์รูปภาพ, HTML5, JavaScript, CSS เปน็ ต้น ใหเ้ กบ็ ไฟลเ์ หล่านี้ไวใ้ นโฟลเดอร์ wwwroot เราถอื วา่ ไฟล์สว่ นแสดงผลต่างๆ ท่ไี ด้ จาก Angular เปน็ ไฟลป์ ระเภท Static เช่นกัน Startup.cs (บางสว่ น) 1 public void Conifgure(IApplicationBuilder app, IHostingEnvironment env) 2{ 3 if (env.IsDevelopment()) 4{ 5 app.UseDeveloperExceptionPage(); 6} 7 else 8{ 9 app.UseExceptionHandler(“/Home/Error”); 10 app.UseHsts(); 11 } 12 13 app.UseHttpsRedirection(); 14 app.UseStaticFiles(); 15 app.UseSpaStaticFiles(); 16 17 app.UseMvc(routes => 18 { 19 routes.MapRoute( 20 name: “default”, 21 template: “{controller}/{action=Index}/{id?}”); 22 }); 23 24 app.UseSpa(spa => 25 { 26 spa.Options.SourcePath = “ClientApp”; 27 264

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core Startup.cs (บางส่วน) ตอ่ 28 if (env.IsDevelopment()) 29 { 30 spa.UseAngularCliServer(npmScript: “start”); 31 } 32 }); 33 } รปู ท่ ี 14-7 แสดงโคด้ ในไฟล์ Startup.cs 2. routes.MapRoute() หมายถงึ การกำ�หนดคอนโทรลเลอร์และเมธอดทท่ี �ำ งานเปน็ ล�ำ ดับแรกในโปรเจ็กต์ โดยปกตแิ ลว้ โปรเจก็ ต์ ASP.NET Core MVC กำ�หนดให้ ÂÂ คอนโทรลเลอร์ทีช่ ่ือวา่ Home ({controler=Home}) ท�ำ งานเปน็ ล�ำ ดบั แรก ÂÂ เมธอดทีช่ ื่อวา่ Index() ({action=Index}) ทำ�งานเปน็ ลำ�ดับแรก ÂÂ พารามิเตอร์ id ({id?}) ของแตล่ ะเมธอดจะมหี รือไมม่ ีก็ได้ ScJraivpat 265

Controllers ใน ASP.NET Core MVC รายการคอนโทรลเลอรต์ า่ งๆ ในโปรเจ็กต์ ต้องเกบ็ อยูใ่ นโฟลเดอรท์ ่ีชอื่ วา่ Controlers วิธีการเรียกช่ือใช้หลักการว่า ค�ำท่ีอยู่ด้านหน้าของค�ำว่า Controller คือ ช่ือเรียก เช่น SampleDataControler จึงมชี ่ือเรียกวา่ SampleData รปู ท่ ี 14-8 แสดงโค้ดในคอนโทรลเลอร์ Home สว่ นแสดงผล (View) ใน ASP.NET Core MVC ทม่ี กี ารใชง้ าน Angular โดยปกตแิ ลว้ ส่วนแสดงผลของ ASP.NET Core MVC ถกู เก็บอยู่ในโฟลเดอรท์ ช่ี ือ่ วา่ Views มีนามสกลุ ไฟล์ .cshtml เชน่ ส่วนแสดงผลของเมธอด Index() ตอ้ งมชี ือ่ ไฟลเ์ หมือนกับ ชือ่ เมธอด นัน่ คือ ไฟล์ Index.cshtml ในกรณโี ปรเจก็ ต์ ASP.NET Core MVC ทมี่ กี ารใชง้ าน Angular สว่ นแสดงผลถกู แทนท่ี ด้วย Angular ท�ำให้ไฟล์สว่ นแสดงผลเหลือเพียงไฟล์เดยี วเท่าน้นั คือ ไฟล์ Index.html ของ Angular ทอี่ ยู่ในพาธ \\ClientApp\\src 266

CHAPTER 14 การใช้งาน Angular ในโลกของ .NET Core รูปที ่ 14-9 แสดงสคริปตใ์ นไฟล์สว่ นแสดงผล Index.html จากรปู ที่ 14-9 ในไฟล์ Index.html เรยี กใชอ้ ลิ เี มนตท์ ชี่ อื่ วา่ หมายถึง ส่วนแสดงผลทไี่ ดจ้ ากคอมโปเนนทท์ ่ีถูกต้งั ชอ่ื ไว้วา่ app-root ท�ำงานเป็นล�ำดบั แรก นน่ั เอง \\ClientApp\\src\\Index.html 1 2 3 4 5 UsingAngularWithASP 6 7 9 10 11 12 Loading... 13 14 ScJraivpat 267

โครงสร้างโปรเจ็กต์ Angular ใน ASP.NET Core MVC โปรเจ็กต์ Angular ถูกสร้างอยู่ในโฟลเดอร์ท่ีช่ือว่า ClientApp พบว่ามีโครงสร้างคล้ายๆ กับโปรเจ็กต์ Angular เด่ียว ดงั รปู ท่ี 14-10 รปู ที่ 14-10 แสดงโครงสร้างโปรเจก็ ต์ Angular ใน ASP.NET Core MVC คอมโปเนนท์ของ Angular ใน ASP.NET Core MVC รายการคอมโปเนนท์ต่างๆ ของ Angular ถกู เก็บอยูใ่ นโฟลเดอร์ components แยก เกบ็ ในแตล่ ะโฟลเดอร์ย่อยตามหนา้ ที่ของตัวเอง ประกอบดว้ ยหนา้ จอยอ่ ย 5 สว่ น 1. app-root เป็นคอมโปเนนท์หลักของ Angular ถูกเรียกใช้เป็นลำ�ดับแรกในไฟล์ Index.html 2. app-counter-component ส�ำ หรบั หนา้ จอทมี่ ีปมุ่ กด Button สำ�หรบั เพิ่มค่าครั้งละ 1 3. app-fetch-data สำ�หรับแสดงข้อมูลแบบสุ่มท่ีได้ จากคอนโทรลเลอรข์ อง ASP.NET Core MVC 4. app-home สว่ นแสดงผลส�ำ หรบั หนา้ จอแรกทมี่ กี าร รอ้ งขอมาท่ีพาธ / 5. app-nav-menu ระบบเมนูทำ�หน้าที่เข้าถึงคอม โปเนนทต์ ่างๆ (หรือเข้าถงึ หน้าจอตา่ งๆ) รูปท ่ี 14-11 แสดงรายการคอมโปเนนทท์ ถ่ี กู สรา้ งขนึ้ มาโดยอัตโนมตั ิ 268

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core 1. ทค่ี อมโปเนนท์ app-root (selector: ‘app-root’) เป็นคอมโปเนนทห์ ลกั ที่ถกู เรยี ก ใช้ในไฟล์ Index.html เป็นลำ�ดับแรก ก็จะกำ�หนดให้ใช้ไฟล์ส่วนแสดงผลที่ช่ือว่า app.component.html (templateUrl: ‘./app.component.html’) และตกแต่ง สว่ นแสดงผลดว้ ยไฟล์app.component.css(styleUrls:[‘./app.component.css’]) \\ClientApp\\src\\app\\app.component.ts 1 import { Component } from ‘@angular/core’; 2 3 @Component({ 4 selector: ‘app-root’, 5 templateUrl: ‘./app.component.html’, 6 styleUrls: [‘./app.component.css’] 7 }) 8 export class AppComponent { 9 title = ‘app’; 10 } รปู ท่ี 14-12 แสดงสครปิ ต์ TypeScript ของไฟล์ app.component.ts ที่ไฟล์ส่วนแสดงผล app.component.html ท�ำหน้าที่สร้างส่วนแสดงผลหลักถูกแบ่ง ออกเปน็ 2 สว่ น ด้วย Bootstrap ÂÂ เมนูหลกั ก�ำ หนดให้ใช้พื้นที่ด้านซ้ายของหนา้ จอ รายการเมนูต่างๆ ถือเปน็ หน้าจอ ยอ่ ยประเภทหนงึ่ ถกู ก�ำ หนดใหอ้ ยใู่ นคอมโปเนนทท์ ชี่ อ่ื วา่ nav-menu() ÂÂ ส่วนแสดงผลแต่ละหน้าจอ หน้าจอต่างๆ เกิดจากการคลิกแต่ละลิงก์สั่งให้คอม โปเนนท์ปรากฎขึ้นมา ตามรายการลิงก์เท่าท่ีมีอยู่ ให้ระบุ ScJraivpat 269

\\ClientApp\\src\\app\\app.component.html 1

2
3
4 5
6
7 8
9
10
OTE Bootstrap เป็น Framework ท�ำ หน้าท่สี ร้างสว่ นแสดงผลแบบ Responsive แสดงผลในหนา้ จอ PC, Notebook, Tablet และมือถอื หลายขนาดได้ในเวลาเดยี วกัน 2. ระบบเมนู อยู่ในความรับผิดชอบของคอมโปเนนท์ท่ีช่ือว่า app-nav-menu (selector: ‘app-nav-menu’) ใชส้ ว่ นแสดงผลทช่ี อ่ื วา่ nav-menu.component.html (templateUrl: ‘./nav-menu.component.html’) รปู ท่ ี 14-13 แสดงสคริปต์ TypeScript ของคอมโปเนนท์ nav-menu.component.ts ทไี่ ฟลส์ ว่ นแสดงผลnav-menu.component.html ท�ำหนา้ ทส่ี รา้ งรายการเมนตู า่ งๆ ขน้ึ มา กจ็ ะใช้Bootstrap เขา้ มาท�ำหนา้ ทส่ี รา้ งรายการเมนรู องรบั การแสดงผลทงั้ แบบหนา้ จอกวา้ ง (PC, Notebook) และหนา้ จอเล็ก (Mobile Devices) ประกอบด้วยรายการเมนหู ลกั 4 เมนู ÂÂ เมนู Home ท�ำ หนา้ ทร่ี ้องขอมาทพี่ าธ / หรือพาธ /home () 270

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core ÂÂ เมนู Counter ท�ำ หนา้ ทร่ี อ้ งขอมาทพ่ี าธ /counter () ÂÂ เมนู Fetch data ทำ�หน้าท่ีร้องขอมาท่ีพาธ /fetch-data () \\ClientApp\\src\\app\\navmenu\\nav-menu.component.html 1

ScJraivpat 271

รปู ที่ 14-14 แสดงรูปแบบเมนใู นหนา้ จอกว้างและหน้าจอเลก็ 3. สว่ นแสดงผลหนา้ แรก home.component.ts อยใู่ นความรบั ผดิ ชอบของคอมโปเนนท์ ท่ีชื่อว่า app-home (selector: ‘app-home’) กำ�หนดใช้ส่วนแสดงผลท่ีชื่อว่า home.component.html (templateUrl: ‘./home.component.html’) รปู ที่ 14-15 คอมโปเนนท์ home สำ�หรับหนา้ จอแรก ในไฟลส์ ว่ นแสดงผลhome.component.html ท�ำหนา้ ทแ่ี สดงขอ้ มลู ทว่ั ไป ดงั รปู ท่ี14-16 รปู ที่ 14-16 ส่วนแสดงผลของคอมโปเนนท์ app-home 272

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core การจัดการเสน้ ทาง (Route) ของ Angular การจดั การเสน้ ทาง (Route) หมายถงึ การก�ำหนดเสน้ ทาง URL รองรบั การรอ้ งขอขอ้ มลู เพอื่ แสดงผลจากคอมโปเนนทต์ ่างๆ เป็นหน้าที่ของไฟล์ app.module.ts ดงั รูปท่ี 14-17 รูปที่ 14-17 ไฟล์จัดการระบบ Route ของ Angular ในกรณีนี้เรามคี อมโปเนนท์ที่ใช้งานในโปรเจ็กตท์ งั้ หมด 5 รายการ ดังน้ี 1. app.component คือ import { AppComponent } from ‘./app.component’ 2. nav-menu.component คือ import { NavMenuComponent } from ‘./ nav-menu/nav-menu.component’ 3. home.component คือ import { HomeComponent } from ‘./home/home. component’ 4. counter.component คือ import { CounterComponent } from ‘./counter/ counter.component’ 5. fetch-data.component คือ import { FetchDataComponent } from ‘./ fetch-data/fetch-data.component’ ScJraivpat 273

\\ClientApp\\app\\app.module.ts 1 import { BrowserModule } from ‘@angular/platform-browser’; 2 import { NgModule } from ‘@angular/core’; 3 import { FormsModule } from ‘@angular/forms’; 4 import { HttpClientModule } from ‘@angular/common/http’; 5 import { RouterModule } from ‘@angular/router’; 6 7 import { AppComponent } from ‘./app.component’; 8 import { NavMenuComponent } from ‘./nav-menu/nav-menu.component’; 9 import { HomeComponent } from ‘./home/home.component’; 10 import { CounterComponent } from ‘./counter/counter.component’; 11 import { FetchDataComponent } from ‘./fetch-data/fetch-data.component’; 12 13 @NgModule({ 14 declarations: [ 15 AppComponent, 16 NavMenuComponent, 17 HomeComponent, 18 CounterComponent, 19 FetchDataComponent 20 ], 21 imports: [ 22 BrowserModule.withServerTransition({ appId: ‘ng-cli-universal’ }), 23 HttpClientModule, 24 FormsModule, 25 RouterModule.forRoot([ 26 { path: ‘’, component: HomeComponent, pathMatch: ‘full’ }, 27 { path: ‘counter’, component: CounterComponent }, 28 { path: ‘fetch-data’, component: FetchDataComponent }, 29 ]) 30 ], 31 providers: [], 32 bootstrap: [AppComponent] 33 }) 34 export class AppModule { } คอมโปเนนทท์ ง้ั 5 ข้างตน้ เราต้องก�ำหนดเส้นทาง Route ท่ี RouterModule รองรับ เพียง 3 เส้นทางเท่าน้นั คือ 1. กรณีร้องขอมาท่ี / หรือ /home หรือเส้นทางอื่นๆ กำ�หนดให้เป็นหน้าท่ีของคอม โปเนนท์ HomeComponent ({ path: ‘’, component: HomeComponent, pathMatch: ‘ful’ }) 274

CHAPTER 14 การใช้งาน Angular ในโลกของ .NET Core 2. กรณรี อ้ งขอมาท่ี/counter ก�ำ หนดใหเ้ ปน็ หนา้ ทข่ี องคอมโปเนนท์CounterComponent ({ path: ‘counter’, component: CounterComponent }) 3. กรณีร้องขอมาท่ี /fetch-data กำ�หนดให้เป็นหน้าท่ขี องคอมโปเนนท์ FetchData Component ({ path: ‘fetch-data’, component: FetchDataComponent }) พนื้ ฐานการทำ�งานกบั เหตกุ ารณ์ในคอมโปเนนทข์ อง Angular ส่วนแสดงผลท่ีเกิดจากคอมโปเนนท์ app-counter-component (selector:‘app- counter-component’) แสดงวิธกี ารผูกเหตกุ ารณ์ รูปที ่ 14-18 สคริปต์ TypeScript ใน counter.component.ts ในคลาส CounterComponent สร้างตวั แปรที่ช่อื วา่ currentCount ก�ำหนดค่าเรมิ่ ตน้ เป็น 0 (public currentCount = 0) ท�ำหนา้ ทเี่ ป็นตวั นับท่เี ราตอ้ งการเพ่มิ คา่ ภายในคลาส CounterComponent มี 1 เมธอดชอ่ื วา่ incrementCounter() ท�ำหนา้ ทเ่ี พิม่ ค่าใหก้ ับตัวแปร currentCount คร้ังละ 1 (this.currentCount++) ดงั สครปิ ตต์ อ่ ไปน้ี \\ClientApp\\src\\app\\counter\\counter.component.ts 1 import { Component } from ‘@angular/core’; 2 3 @Component({ 4 selector: ‘app-counter-component’, 5 templateUrl: ‘./counter.component.html’ 6 }) 7 export class CounterComponent { 8 public currentCount = 0; 9 10 public incrementCounter() { 11 this.currentCount++; 12 } 13 } ScJraivpat 275

ที่ไฟล์ส่วนแสดงผล counter.component.html ส่ังให้ผูกเหตุการณ์ click เข้ากับ เมธอดincrementCounter()() สง่ ผลใหท้ กุ ๆ ครง้ั ท่ี คลกิ ท่ีปมุ่ กด Button เป็นการเพิม่ ค่าครัง้ ละ 1 ดังสครปิ ตต์ ่อไปน้ี \\ClientApp\\src\\app\\counter\\counter.component.html 1

Counter

2

This is a simple example of an Angular component.

3

Current count: {{ currentCount }}

4 การทำ�งานรว่ มกนั ระหวา่ งคอนโทรลเลอร์ของ ASP.NET Core MVC กับคอมโปเนนทข์ อง Angular เปา้ หมายหลักของการน�ำ Angular มาใช้งานในโปรเจ็กตข์ อง ASP.NET Core MVC กค็ อื ท�ำหนา้ ทีเ่ ป็นสว่ นแสดงผลอยใู่ นฐานะเปน็ หน้าบา้ น สว่ น ASP.NET Core MVC อยู่ใน ฐานะเป็นหลังบ้าน ส่งผลให้เกิดการท�ำงานร่วมกนั ระหวา่ งคอนโทรลเลอรข์ อง ASP.NET Core MVC กับคอมโปเนนทข์ อง Angular อยูใ่ นคอมโปเนนท์ app-fetch-data (selector: ‘app- fetch-data’) รปู ท ี่ 14-19 แสดงสคริปต์ TypeScript ของคอมโปเนนท์ app-fetch-data 1. หน้าท่ขี องคอมโปเนนท์ fetchdata (selector: ‘app-fetch-data’) ก็คอื รอ้ งขอ ข้อมูลไปท่ีพาธ api/SampleData/WeatherForecasts เป็นข้อมูลท่ีถูกสุ่มข้ึนมา (เป็นการทำ�งานทเ่ี กดิ ขน้ึ หลังบ้าน) ผลการทำ�งานแสดงในไฟล์ส่วนแสดงผลทช่ี อ่ื ว่า fetch-data.component.html (templateUrl: ‘./fetch-data.component.html’) 276

CHAPTER 14 การใช้งาน Angular ในโลกของ .NET Core \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.ts 1 import { Component, Inject } from ‘@angular/core’; 2 import { HttpClient } from ‘@angular/common/http’; 3 4 @Component({ 5 selector: ‘app-fetch-data’, 6 templateUrl: ‘./fetch-data.component.html’ 7 }) 8 export class FetchDataComponent { 9 public forecasts: WeatherForecast[]; 10 11 constructor(http: HttpClient, @Inject(‘BASE_URL’) baseUrl: string) { 12 http.get(baseUrl + ‘api/SampleData/WeatherForecasts’).subscribe(result => { 13 this.forecasts = result; 14 }, error => console.error(error)); 15 } 16 } 17 18 interface WeatherForecast { 19 dateFormatted: string; 20 temperatureC: number; 21 temperatureF: number; 22 summary: string; 23 } 2. ท่ีคอนโทรลเลอร์ SampleDataController ทำ�หน้าท่ีสุ่มข้อมูลสภาพอากาศขึ้นมา ดังโคด้ ตอ่ ไปน้ี \\Controllers\\SampleDataController.cs 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.Mvc; 6 7 namespace UsingAngularWithASP.Controllers 8{ 9 [Route(“api/[controller]”)] 10 public class SampleDataController : Controller 11 { 12 private static string[] Summaries = new[] 13 { ScJraivpat 277

\\Controllers\\SampleDataController.cs (ต่อ) 1 “Freezing”, “Bracing”, “Chilly”, “Cool”, “Mild”, “Warm”, “Balmy”, “Hot”, “Sweltering”, 2 “Scorching” 3 }; 4 5 [HttpGet(“[action]”)] 6 public IEnumerable WeatherForecasts() 7{ 8 var rng = new Random(); 9 return Enumerable.Range(1, 5).Select(index => new WeatherForecast 10 { 11 DateFormatted = DateTime.Now.AddDays(index).ToString(“d”), 12 TemperatureC = rng.Next(-20, 55), 13 Summary = Summaries[rng.Next(Summaries.Length)] 14 }); 15 } 16 17 public class WeatherForecast 18 { 19 public string DateFormatted { get; set; } 20 public int TemperatureC { get; set; } 21 public string Summary { get; set; } 22 23 public int TemperatureF 24 { 25 get 26 { 27 return 32 + (int)(TemperatureC / 0.5556); 28 } 29 } 30 } 31 } 32 } 3. ท้ายท่ีสุด ผลการทำ�งานท่ีได้แสดงผลในไฟล์ fetch-data.component.html ดงั สคริปตต์ อ่ ไปนี้ \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.html 1

Weather forecast

2

This component demonstrates fetching data from the server.

3 4

Loading...

278

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.html (ต่อ) 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
DateTemp. (C)Temp. (F)Summary
{{ forecast.dateFormatted }}{{ forecast.temperatureC }}{{ forecast.temperatureF }}{{ forecast.summary }}
อธิบายการท�ำ งานของโคด้ 1. เริ่มต้น เมื่อมีการร้องขอมาท่ีพาธ /fetch-data เป็นการสั่งให้คอมโปเนนท์ท่ีชื่อ ว่า fetchdata ทำ�งาน ในคลาส FetchDataComponent สร้างตัวแปรท่ีชื่อว่า forecasts ก�ำ หนดใหม้ ชี นดิ ขอ้ มลู เปน็ อนิ เตอรเ์ ฟสทชี่ อื่ วา่ WeatherForecast(public forecasts: WeatherForecast[]) ตวั แปร forecasts ท�ำหนา้ ทเ่ี กบ็ ผลการท�ำงานทไี่ ดจ้ ากหลงั บา้ น (ไดจ้ ากการท�ำงานของ ASP.NET Core MVC) \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.ts 1 export class FetchDataComponent { 2 public forecasts: WeatherForecast[]; อินเตอร์เฟส WeatherForecast เป็นข้อบังคับท่ีสร้างขึ้นมาเอง ท�ำหน้าที่ก�ำหนด โครงสร้างข้อมลู ท่ีเราตอ้ งการ ในกรณนี ้บี ังคบั ไว้วา่ ตอ้ งมีขอ้ มลู 4 ส่วนเท่าน้นั คือ ÂÂ dateFormatted มีชนิดขอ้ มลู เปน็ ข้อความ string ท�ำ หน้าทเี่ กบ็ ขอ้ มูลวนั ที่ ÂÂ temperatureC มีชนิดข้อมูลเป็นตัวเลข number ทำ�หน้าที่เก็บอุณหภูมิในหน่วย องศาเซลเซยี ส ScJraivpat 279

ÂÂ temperatureF มีชนิดข้อมูลเป็นตัวเลข number ทำ�หน้าที่เก็บอุณหภูมิในหน่วย ฟาเรนไฮต์ ÂÂ summary มชี นิดข้อมูลเป็นขอ้ ความ string ท�ำ หนา้ ทเ่ี ก็บคำ�เรียกสภาวะอากาศ \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.ts 1 interface WeatherForecast { 2 dateFormatted: string; 3 temperatureC: number; 4 temperatureF: number; 5 summary: string; 6} 2. ต่อมา ท่ีคอนสทรกั เตอร์ เราจะสัง่ ใหค้ อมโปเนนท์ app-fetch-data ร้องขอขอ้ มูล แบบ get (http.get) ไปที่ ASP.NET Core MVC (อยูใ่ นฐานะเป็น Web API กไ็ ด)้ รปู แบบ/api/ชอื่ คอนโทรลเลอร/์ ชอ่ื เมธอด ในกรณนี เ้ี ราตอ้ งการขอ้ มลู จากพาธapi/ SampleData/WeatherForecasts \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.ts 1 constructor(http: HttpClient, @Inject(‘BASE_URL’) baseUrl: string) { 2 http.get(baseUrl + ‘api/SampleData/WeatherForecasts’).subscribe(result => { 3. ต่อมา ข้อมูลที่ได้มาจากพาธดังกล่าวถูกส่งมาในรูปแบบ JSON เก็บข้อมูลไว้ใน ตวั แปรทีชือ่ ว่า forecasts (this.forecasts) \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.ts 1 this.forecasts = result; สง่ิ ทีเ่ ราสนใจกค็ อื พาธข้างตน้ มที ม่ี าอย่างไร 4. ต่อมา ที่คอนโทรลเลอร์ SampleData ของ ASP.NET Core MVC พบว่ามีการ กำ�กับเส้นทาง Route ไว้ในขั้นต้นว่า api/ชื่อคอนโทรลเลอร์ ในกรณีน้ี คือ api/ SampleData นัน่ เอง \\Controllers\\SampleDataController.cs 1 [Route(“api/[controller]”)] 2 public class SampleDataController : Controller 3{ 280

CHAPTER 14 การใช้งาน Angular ในโลกของ .NET Core 5. ตอ่ มา สร้างตวั แปรอาร์เรย์ท่ีช่ือวา่ Summaries ท�ำ หน้าท่เี ก็บขอ้ ความบอกสถานะ อากาศแต่ละแบบ \\Controllers\\SampleDataController.cs 1 private static string[] Summaries = new[] 2{ 3 “Freezing”, “Bracing”, “Chilly”, “Cool”, “Mild”, “Warm”, “Balmy”, “Hot”, “Sweltering”, 4 “Scorching” 5 }; 6. ต่อมา ท่ีเมธอด WeatherForecasts() เป็นเมธอดหลักของการทำ�งานน้ี ถ้า เราต้องการส่ังให้เมธอดน้ีทำ�งาน เมื่อรวมพาธทั้งหมดเข้าด้วยกันก็จะได้ api/ SampleData/WeatherForecasts นนั่ เอง \\Controllers\\SampleDataController.cs 1 [HttpGet(“[action]”)] 2 public IEnumerable WeatherForecasts() 3{ เหน็ ไดว้ า่ เมธอดWeatherForecasts() ถกู ก�ำหนดใหค้ นื คา่ เปน็ คลาสWeatherForecast (public IEnumerable) ต้องตรงกับอนิ เตอรเ์ ฟส WeatherForecast ที่ เราก�ำหนดไว้ที่คอมโปเนนท์ fetchdata กอ่ นหน้าน้ีนัน่ เอง \\Controllers\\SampleDataController.cs 1 public class WeatherForecast 2{ 3 public string DateFormatted { get; set; } 4 public int TemperatureC { get; set; } 5 public string Summary { get; set; } 6 7 public int TemperatureF 8{ 9 get 10 { 11 return 32 + (int)(TemperatureC / 0.5556); 12 } 13 } 14 } ScJraivpat 281

7. ต่อมา การทำ�งานภายในเมธอด WeatherForecasts() โดยการส่มุ ขอ้ มลู ขนึ้ มา ผล การสุม่ ขอ้ มลู ทไ่ี ดถ้ ูกส่งออกไปตามโครงสรา้ งของคลาส WeatherForecast เพ่อื ให้ คอมโปเนนท์ app-fetch-data แสดงผลตอ่ ไป \\Controllers\\SampleDataController.cs 1 var rng = new Random(); 2 return Enumerable.Range(1, 5).Select(index => new WeatherForecast 3{ 4 DateFormatted = DateTime.Now.AddDays(index).ToString(“d”), 5 TemperatureC = rng.Next(-20, 55), 6 Summary = Summaries[rng.Next(Summaries.Length)] 7 }); 8} การท�ำงานของเมธอด WeatherForecasts() มดี ังน้ี ÂÂ สมุ่ ขอ้ มลู 5 ชดุ (Enumerable.Range(1,5)) มโี ครงสรา้ งแบบคลาสWeatherForecast (new WeatherForecast) ÂÂ สุ่มวันท่ี ใช้วันท่ีปัจจุบันเป็นวันเริ่มต้น (DateFormatted = DateTime.Now. AddDays(index).ToString(“d”)) ÂÂ สมุ่ อณุ หภมู ิ ในชว่ ง-20 ถงึ 55 องศาเซลเซยี ส(TemperatureC=rng.Next(-20,55)) ÂÂ สุ่มคำ�เรียกสถานะอุณหภูมิ (Summary = Summaries[rng.Next(Summaries. Length)]) 8. ตอ่ มา ไฟลแ์ สดงผลของคอมโปเนนท์ fetchdata คอื ไฟล์ fetchdata.component. html ใหต้ รวจสอบกอ่ นเลยวา่ ถา้ ตวั แปรforecasts ไมม่ ขี อ้ มลู (*ngIf=“!forecasts”) ให้แสดงขอ้ ความ Loading… \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.html 1

Loading...

282

CHAPTER 14 การใชง้ าน Angular ในโลกของ .NET Core 9. ต่อมา ในกรณีตัวแปร forecasts มีข้อมูล (*ngIf=“forecasts”) ก็จะส่ังให้แสดง ขอ้ มลู ในรปู แบบตาราง ใหส้ ร้างหัวตารางข้นึ มาก่อน โดยอาศัยอลิ เี มนต์

… จ�ำ นวน 4 คอลัมน์ \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.html 1 2 3 4 5 6 7 8 9 10. ต่อมา สง่ั ใหว้ นลูปอา่ นข้อมลู ท่ีเกบ็ อยใู่ นตวั แปร forecasts (*ngFor=“let forecast of forecasts”) ออกมาตามโครงสร้างของอนิ เตอรเ์ ฟส WeatherForecast น�ำ มาส ร้างเป็นข้อมูลในแต่ละแถว วนลูปจนครบทุกรายการก็จะได้ข้อมูลที่มาจากการ ทำ�งานของคอนโทรลเลอร์ SampleData แลว้ (หรอื เรียกว่า ได้ข้อมูลมาจาก Web API กไ็ ด)้ \\ClientApp\\src\\app\\fetch-data\\fetch-data.component.html 1 2 3 4 5 6 7 8 9
DateTemp. (C)Temp. (F)Summary
{{ forecast.dateFormatted }}{{ forecast.temperatureC }}{{ forecast.temperatureF }}{{ forecast.summary }}
ScJraivpat 283

สรปุ ท้ายบท จุดประสงค์ของเน้ือหาในบทนี้ ก็คือ ผู้เขียนต้องการแสดงให้คุณเห็นว่า Angular มีบทบาทในเรื่องของการสร้างส่วนแสดงผลในโลกของ Web Apps เป็น อยา่ งมาก จึงเป็นอีก 1 หัวข้อท่นี ักพฒั นาในยคุ ปัจจบุ นั ไมค่ วรพลาด 284

Java script 15CHAPTER การสรา้ งสว่ นแสดงผลแสดงในหนา้ จอทกุ ขนาด (Responsive Design) การพัฒนา Web Apps ในทุกแพลตฟอร์มทุกภาษาในยุคปัจจุบัน หนึ่งในความสามารถ ท่ีต้องมีน่ันคือ การสร้างส่วนแสดงผลท่ีสามารถแสดงผลในหน้าจอทุกขนาด เรียกว่า Responsive Design โดยที่ผู้เขียนเลือกใช้ Bootstrap เข้ามารับผิดชอบในหน้าที่นี้ หลกั การทำ�งานพ้ืนฐานของ Bootstrap เพื่อให้เข้าใจหลักการท�ำงานของ Bootstrap ให้เร็วท่ีสุด และง่ายท่ีสุด ผู้เขียนสรุป หลกั การทำ� งานไว้ดงั น้ี 1. ความกว้างของหน้าจอถูกก�ำหนดให้มีขนาดเท่ากับกล่องส่ีเหลี่ยม 12 ใบ เรียง ตอ่ กันจนเตม็ ความกว้างของส่วนแสดงผลหรือหน้าจอ เรียกว่า “ระบบ Grid หรือ Grid System” 2. กล่องส่ีเหล่ียมดงั กล่าว มี 5 ขนาด แสดงดังตารางตอ่ ไปน้ี ขนาดความกว้างหนา้ จอ คลาสท่ใี ช้ นอ้ ยกวา่ 576 พกิ เซล (เล็กสุด) .col- มากกว่าหรือเทา่ กบั 576 พิกเซล .col-sm- มากกวา่ หรือเท่ากับ 768 พกิ เซล .col-md- มากกว่าหรอื เทา่ กับ 960 พิกเซล .col-lg- มากกวา่ หรือเทา่ กับ 1140 พิกเซล (ใหญ่สุด) .col-xl- HTML .Net HTML

การตดิ ตง้ั Bootstrap ในโปรเจก็ ตแ์ บบ Mongo, Express และ Node โปรเจก็ ต์ CRUD ทนี่ ำ� เสนอในบทท่ี 10 มแี ตก่ ารทำ� งานลว้ นๆ ผเู้ ขยี นไมส่ นใจสว่ นแสดง ผลในแตล่ ะหนา้ จอเลยวา่ จะสวยหรอื ไมส่ วยอยา่ งไร ตอ้ งการใหไ้ ดก้ ารทำ� งานทเี่ ราตอ้ งการเทา่ นนั้ ตวั อย่างที่ 15-1 การใช้งาน Bootstrap ในโปรเจ็กต์ CRUD เปา้ หมายของบทนกี้ ค็ อื ตอ้ งการปรบั ปรงุ ใหโ้ ปรเจก็ ต์ CRUD สามารถแสดงผลไดท้ งั้ ในหนา้ จอใหญ่ (PC) และหนา้ จอเลก็ (มอื ถอื หรอื แทบ็ เลต็ ) โดยอาศยั Bootstrap มขี นั้ ตอนดงั นี้ 1. ไปทเ่ี วบ็ ไซต์ getbootstrap.com/ เลอื ก Getting Started เพอ่ื ตรวจสอบวธิ กี ารตดิ ตงั้ ขอบเขตการนำ� เสนอในบทนค้ี อื ใชง้ าน Bootstrap เวอรช์ นั 4.1.1 ขน้ึ ไป ดงั รปู ที่ 10-1 รปู ที ่ 15-1 แสดงวิธีการติดต้ัง Bootstrap จากรปู ที่ 10-1 การใชง้ าน Bootstrap ต้องอาศยั jQuery ด้วย มที ัง้ ส่วนทีเ่ ปน็ CSS และ JavaScript ในกรณนี ้ีเราต้องการน�ำ Bootstrap มาใชก้ ับสว่ นแสดงผลท่ีเกดิ จากชนิ้ สว่ นทช่ี ือ่ ว่า Pug ส่งผลให้เราไม่สามารถ Copy มาใชง้ านโดยตรงตามข้อแนะนำ� ในหน้าเว็บไซด์ ตอ้ งมี การแปลงไวยากรณต์ ามรปู แบบของ Pug เสียกอ่ น 2. ในโปรเจ็กต์ CRUD ที่ไฟล์ layout.pug ท�ำหน้าท่ีก�ำหนดโครงสร้างไฟล์ HTML5 ท้งั หมด ใหอ้ า้ งอิงใช้งานส่วน CSS และ JavaScript ของ Bootstrap ใหค้ รบถ้วน ดงั สคริปต์ต่อไปน้ี 286

CHAPTER 15 การสร้างสว่ นแสดงผลแสดงในหน้าจอทุกขนาด (Responsive Design) สคริปต์ Pug ท่ี 15-1 การใช้งาน Bootstrap ในโปรเจ็กต์ CRUD (layout.pug) 1 doctype html 2 html 3 head 4 title= title 5 link(rel=’stylesheet’, href=’https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap. 6 min.css’) 7 8 body 9 section 10 include mainmenu 11 include search 12 block content 13 include mainfooter 14 script(src=’https://code.jquery.com/jquery-3.3.1.slim.min.js’) 15 script(src=’https://cdnjs.cloudfal re.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js’) 16 script(src=’https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js’) จากสคริปต์ Pug ขา้ งตน้ คอื ÂÂ สว่ นของเมนหู ลกั เกบ็ อยใู่ น mainmenu.pug (ไฟลเ์ ดมิ ) ÂÂ สว่ นของการค้นหา เก็บอยูใ่ น search.pug (เพิม่ เขา้ ใหม่) รูปท่ี 15-2 แสดงสครปิ ตใ์ นไฟล์ layout.pug จากรปู ที่10-2 หลงั จากทอี่ า้ งองิ สว่ นCSS และJavaScript ของBootstrap ครบถว้ นแลว้ เราสามารถใช้ Bootstrap ทีม่ กี ารแปลงไวยากรณ์แบบ Pug ในโปรเจ็กต์ CRUD ของเราไดแ้ ล้ว 3. ระบบเมนู เลอื กใชแ้ บบ Navbar ของ Bootstrap กำ� หนดใหม้ ลี งิ ก์ 3 สว่ นเชน่ เดมิ คอื ÂÂ หน้าแรก โดยการรอ้ งขอไปทพ่ี าธ / ÂÂ แสดงรายการหนงั สอื โดยการร้องขอไปทีพ่ าธ /books ÂÂ แสดงรายการสมาชกิ โดยการรอ้ งขอไปท่พี าธ /users ScJraivpat 287

สคริปต์ Pug ท่ี 15-1 การใชง้ าน Bootstrap ในโปรเจก็ ต์ CRUD (add.pug) (ต่อ) 12 div.col-6 13 label(for=”price”) ราคา : 14 input

price.form-control(type=”text”, size=”30”, placeholder=”ราคา”) 15 div.col-6 16 button.btn.btn-primary(type=”submit”) บันทึก 6. ทา้ ยทส่ี ดุ สว่ นของการคน้ หา ผเู้ ขยี นแยกออก มาเป็นไฟล์ต่างหากช่ือว่า search.pug ท่ี ส�ำคญั กค็ ือ รปู ท ่ี 15-5 แบบฟอรม์ เพ่ิมหนงั สอื ใหม่ ÂÂ กำ�หนดให้อยู่ก่ึงกลางหน้าจอเสมอ กำ�หนด ผ่านทางแอ็ตทริบิวต์ .row.justify-content- center ÂÂ ปุ่มกดค้นหา กำ�หนดให้ใช้รูปแบบ primary ปุ่มสีฟ้า ผ่านทางแอ็ตทริบิวต์ .btn.btn- primary สคริปต์ Pug ที่ 15-1 การใช้งาน Bootstrap ในโปรเจ็กต์ CRUD (search.pug) 1 form(action=’/books/search’, method=’post’) 2 div.form-inline.row.justify-content-center 3 input.form-control(type=’text’, name=’q’, size=’80’, style=’margin: 3px;’, 4 placeholder=’ค้นหาข้อมูล...’) 5 input.btn.btn-primary(type=’submit’, value=’คน้ หา’ style=’margin-left: 3px;’) สรุปท้ายบท การพัฒนา Web Apps บนแพลตฟ์ อรม์ MEAN Stack ผูเ้ ขยี นเน้นเนือ้ หามา ท่ี MongoDB, Express, Node เป็นหลกั และนำ� เสนอเน้อื หาของ Angular เล็กนอ้ ย บางส่วน เพือ่ ให้คุณผ้อู า่ นเหน็ ภาพโดยรวม...สวสั ดคี รับ 290