เพิ่มหน้าจัดการ User
Workshop special - เพิ่มหน้าจัดการ user
เราจะเพิ่มหน้า user ทั้งหมดออกมาโดยจะเพิ่มหน้าเหล่านี้มาโดย เราจะเพิ่ม users.html
เข้ามาเพื่อเพิ่ม feature เหล่านี้เข้าไป
- list user ทั้งหมด
- แก้ไข user ได้
- ลบ user ได้
1. เพิ่มหน้า users.html สำหรับ list user ทั้งหมดออกมา
- สร้าง
users.html
, และusers.js
- ที่
users.html
เพิ่มแค่ dom div id=users ออกมาแค่นั้น (เพื่อใช้สำหรับแสดงข้อมูล)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>หน้ารวม Users</h1>
<div id="users"></div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="users.js"></script>
</body>
</html>
- ที่
users.js
ทำการเพิ่มตัวแปรสำหรับเก็บ base host มา (เนื่องจากจะใช้หลาย function) และทำการดึงข้อมูล users ทั้งหมดออกมาแสดง - เพิ่ม window.onload มาเพื่อ recheck ก่อนว่า browser พร้อมแล้วหรือไม่ ก่อนโหลดข้อมูลเข้ามา และทำการแยก function
loadData()
สำหรับการโหลดข้อมูล
const BASE_URL = 'http://localhost:8000'
window.onload = async () => {
await loadData()
}
const loadData = async () => {
// get user ทั้งหมดออกมา
const response = await axios.get(`${BASE_URL}/users`)
const users = response.data
// ประกอบ HTML จาก user data โดยใช้ <li> และ สร้างปุ่มสำหรับ Edit และ Delete
let userHTMLData = '<ul>'
for (let i = 0; i < users.length; i++) {
userHTMLData += `<li>
${users[i].firstname} ${users[i].lastname}
<a href='index.html?id=${users[i].id}'><button data-id='${users[i].id}'>Edit</button></a>
<button class='delete' data-id='${users[i].id}'>Delete</button>
</li>`
}
userHTMLData += '</ul>'
// นำ html ที่ประกอบใส่กลับเข้าไปใน DOM html
let usersDOM = document.getElementById('users')
usersDOM.innerHTML = userHTMLData
}
2. กด ลบ = สามารถ ลบ user ได้
const loadData = async () => {
... // เพิ่มต่อจากส่วนที่ดึงข้อมูล user
// ทำการดึง button class=delete ที่ติดกับทุก DOM ที่สร้างใหม่มา
let deleteDOMs = document.getElementsByClassName('delete')
// หลังจากนั้น ทำการวนลูปไปยังทุก DOM และเพิ่ม click event
for (let i = 0; i < deleteDOMs.length; i++) {
deleteDOMs[i].addEventListener('click', async (event) => {
// ดึงค่า id ที่ฝังไว้กับ data-id เพื่อใช้สำหรับ reference กลับไปยังฝั่ง Backend
let id = event.target.dataset.id
try {
await axios.delete(`${BASE_URL}/users/${id}`)
loadData()
} catch (error) {
console.log('error', error)
}
})
}
}
3. กด แก้ไข = สามารถไปหน้าเดิม
และนี่คือโจทย์ยากที่สุดของ Session นี้คือ เราจะทำให้ user สามารถแก้ไขจากหน้าเดิมได้อย่างไร ? วิธีการที่ง่ายที่สุด = paramater
- เพิ่ม tag
<a href='index.html?id=${id}'></a>
ครอบปุ่มไว้ เพื่อให้สามารถกลับไปยังหน้าเดิมพร้อม parameter ได้
const loadData = async () => {
...
for (let i = 0; i < users.length; i++) {
userHTMLData += `<li>
${users[i].firstname} ${users[i].lastname}
<a href='index.html?id=${users[i].id}'><button>Edit</button></a>
<button class='delete' data-id='${users[i].id}'>Delete</button>
</li>`
}
...
}
- กลับมาที่หน้า
index.js
ประกาศตัวแปร base host ร่วมด้านบน และสร้างตัวแปรสำหรับเก็บ mode และ id เอาไว้
- พร้อมกันเพิ่ม
window.onload
เข้ามาเพื่อเช็คว่ามี id จาก paramater เข้ามาหรือไม่
const BASE_URL = 'http://localhost:8000'
// default mode ของหน้านี้คือ mode สร้าง
let mode = 'CREATE'
let selectedId = -1
window.onload = async () => {
// นำ parameter ทั้งหมดมาใส่ตัวแปร urlParams
const urlParams = new URLSearchParams(window.location.search)
// ดึง id ออกมาจาก parameter
const id = urlParams.get('id')
if (id) {
// ถ้ามี id = เปลี่ยน mode และเก็บตัวแปร id เอาไว้
mode = 'EDIT'
selectedId = id
}
}
- ที่
index.js
ต่อ เราจะทำการ prefill ข้อมูลทั้งหมดเข้า form โดยเราจะประกาศตัวแปรทั้งหมดที่ใส่ form ได้ และดึงข้อมูลจาก API มาใส่ form เหล่านั้น
window.onload = async () => {
const urlParams = new URLSearchParams(window.location.search)
const id = urlParams.get('id')
if (id) {
mode = 'EDIT'
selectedId = id
// select ทุก dom ออกมา
let firstNameDOM = document.querySelector('input[name=firstname]')
let lastNameDOM = document.querySelector('input[name=lastname]')
let ageDOM = document.querySelector('input[name=age]')
let genderDOMs = document.querySelectorAll('input[name=gender]')
let interestDOMs = document.querySelectorAll('input[name=interest]')
let descriptionDOM = document.querySelector('textarea[name=description]')
try {
const response = await axios.get(`${BASE_URL}/users/${id}`)
const user = response.data
// เริ่มทำการใส่ข้อมูล
firstNameDOM.value = user.firstname
lastNameDOM.value = user.lastname
ageDOM.value = user.age
descriptionDOM.value = user.description
for (let i = 0; i < genderDOMs.length; i++) {
if (genderDOMs[i].value == user.gender) {
genderDOMs[i].checked = true
}
}
const interests = user.interests.split(',').map(interest => interest.trim())
for (let i = 0; i < interestDOMs.length; i++) {
if (interests.includes(interestDOMs[i].value)) {
interestDOMs[i].checked = true
}
}
} catch (error) {
console.log('error', error)
}
}
}
- ที่
index.js
ที่ submitData() ปรับที่ตอนยิง API สร้างให้โดย
- ถ้า mode = CREATE ยิงที่เส้นเดิม POST /users
- ถ้า mode = EDIT ยิงที่เส้น PUT /users/:id และนำ id จาก selectedId มาใส่
const submitData = async () => {
try {
...
let userData = {
firstname: firstNameDOM.value,
lastname: lastNameDOM.value,
age: ageDOM.value,
gender: genderDOM.value,
description: descriptionDOM.value,
interests: interest
}
...
let response = {}
let successText = 'เพิ่มข้อมูลเรียบร้อย !'
// เพิ่ม condition มาดักเรื่อง mode เอาไว้
if (mode == 'EDIT') {
// นำ selectedId เอาไว้
response = await axios.put(
`${BASE_URL}/users/${selectedId}`,
userData
)
// เปลี่ยน message เมื่อเป็นเคสแก้ไข
successText = 'แก้ไขข้อมูลเรียบร้อย !'
} else {
response = await axios.post(
`${BASE_URL}/users`,
userData
)
}
responseMessageDOM.innerText = successText
responseMessageDOM.className = 'message success'
} catch (error) {
...
}
}
และนี่ก็คือทั้งหมดทั้งมวลของเว็บไซต์เรา ! ทั้งหมดที่เราทำมานี้
- ยังไม่มีเรื่อง Authentication (ดักว่าใครแก้ไขได้หรือไม่ได้)
- เดี๋ยวเราจะสรุปทั้งหมดทั้งมวลกันในบทต่อไปก่อนจบ web development 101 กัน