Skip to main content

เพิ่มหน้าจัดการ User

Workshop special - เพิ่มหน้าจัดการ user

เราจะเพิ่มหน้า user ทั้งหมดออกมาโดยจะเพิ่มหน้าเหล่านี้มาโดย เราจะเพิ่ม users.html เข้ามาเพื่อเพิ่ม feature เหล่านี้เข้าไป

  • list user ทั้งหมด
  • แก้ไข user ได้
  • ลบ user ได้

1. เพิ่มหน้า users.html สำหรับ list user ทั้งหมดออกมา

  1. สร้าง 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

  1. เพิ่ม 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>`
}
...
}
  1. กลับมาที่หน้า 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
}
}
  1. ที่ 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)
}
}
}
  1. ที่ 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) {
...
}
}

และนี่ก็คือทั้งหมดทั้งมวลของเว็บไซต์เรา ! ทั้งหมดที่เราทำมานี้ user-1

  • ยังไม่มีเรื่อง Authentication (ดักว่าใครแก้ไขได้หรือไม่ได้)
  • เดี๋ยวเราจะสรุปทั้งหมดทั้งมวลกันในบทต่อไปก่อนจบ web development 101 กัน