keyboard_tabSkip to content
listWeb Development 101

เพิ่มหน้าจัดการ 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
<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() สำหรับการโหลดข้อมูล
javascript
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 ได้

javascript
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 ได้
javascript
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 เข้ามาหรือไม่
javascript
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 เหล่านั้น
javascript
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 มาใส่
javascript
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 กัน