こんにちは、プログラマーVTuberの衣亥栖ティオです。
今回は以下の動画の補足説明をします。
動画内で実装したソースコードも載せています。
以下が今回実装したソースコードです。
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<title>メモ帳アプリ</title>
</head>
<body>
<div>
<h3>メモの登録</h3>
title<input type="text" id="id-title"><br>
body<textarea id="id-body"></textarea><br>
<button id="id-add-button">メモを登録する</button>
</div>
<div>
<h3>メモの一覧</h3>
<button id="id-delete-button">削除する</button>
<table class="table">
<thead>
<tr>
<th scope="col"><input type="checkbox" id="id-delete-all-memos"></th>
<th scope="col">タイトル</th>
<th scope="col">作成日</th>
<th scope="col">更新日</th>
<th scope="col">編集</th>
</tr>
</thead>
<tbody id="id-memo-list">
</tbody>
</table>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">編集</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<span class="input-group-text" id="inputGroup-sizing-default">タイトル</span>
<input type="text" id="id-modal-title" class="form-control" aria-label="Sizing example input"
aria-describedby="inputGroup-sizing-default">
</div>
<div class="form-floating">
<textarea class="form-control" style="height: 150px;" placeholder="Leave a comment here"
id="floatingTextarea"></textarea>
<label for="floatingTextarea">本文</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj"
crossorigin="anonymous"></script>
</body>
<script>
const titleElement = document.getElementById("id-title")
const bodyElement = document.getElementById("id-body")
const addButton = document.getElementById("id-add-button")
addButton.addEventListener("click", (event) => {
const title = titleElement.value
const body = bodyElement.value
const now = new Date()
const createdAt = now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate()
const updatedAt = "なし"
const memoId = now.getTime()
const tr = document.createElement("tr")
tr.setAttribute("id", memoId)
const editButtonId = "id-edit-button-" + memoId
const idTitleInList = "id-title-in-list-" + memoId
tr.innerHTML = '<td><input class="class-checkbox" data-memo-id="' + memoId + '" type="checkbox"></td><td id="' + idTitleInList + '">' + title + '</td><td>' + createdAt + '</td><td>' + updatedAt + '</td><td><button type="button" data-memo-id="' + memoId + '" id="' + editButtonId + '" class="btn btn-primary">編集</button></td>'
const memoList = document.getElementById("id-memo-list")
memoList.appendChild(tr)
const editButton = document.getElementById(editButtonId)
editButton.addEventListener("click", (event) => {
const memoId = event.currentTarget.dataset.memoId
const title = document.getElementById("id-title-in-list-" + memoId).innerText
const titleElement = document.getElementById("id-modal-title")
titleElement.value = title
const myModal = new bootstrap.Modal(document.getElementById('exampleModal'))
myModal.show()
})
})
const deleteButton = document.getElementById("id-delete-button")
deleteButton.addEventListener("click", (event) => {
const checkboxes = document.getElementsByClassName("class-checkbox")
Array.from(checkboxes).forEach((checkbox) => {
if (checkbox.checked == false) {
return false
}
const memoId = checkbox.dataset.memoId
document.getElementById(memoId).remove()
})
})
const deleteAllMemos = document.getElementById("id-delete-all-memos")
deleteAllMemos.addEventListener("change", (event) => {
const checkboxes = document.getElementsByClassName("class-checkbox")
if (checkboxes.length == 0) {
return
}
Array.from(checkboxes).forEach((checkbox) => {
if (deleteAllMemos.checked == true) {
checkbox.checked = true
} else {
checkbox.checked = false
}
})
})
</script>
</html>
押された編集ボタンの要素を取得する
動画ではメモ一覧に表示されているタイトルをモーダルにセットする処理を作っていますが、
その際に "押された編集ボタンの要素" を取得しています。
実際のコードが以下です。
editButton.addEventListener("click", (event) => {
const memoId = event.currentTarget.dataset.memoId
})
addEventListener() の引数である event にはクリックに関する様々な情報が格納されています。
Event - Web API | MDN
上記のコードでは押された編集ボタンの要素である currentTarget を利用することで、
編集ボタンにセットした memo-id を取得しています。
Event.currentTarget - Web API | MDN
getElementById() から直接プロパティを参照する
以下のように getElementById() に直接 ".(ドット)" をつなげることで、直接プロパティを参照することができます。
const editButton = document.getElementById(editButtonId)
editButton.addEventListener("click", (event) => {
const memoId = event.currentTarget.dataset.memoId
const title = document.getElementById("id-title-in-list-" + memoId).innerText
以下のように titleInListElement という変数にHTML要素を格納してから、
title 変数にタイトルを代入してもよいのですが、
HTML要素を titleInListElement 変数を利用する必要がない(無駄な変数を定義する必要はない)ので、
getElementById() から直接プロパティを参照する方法で実装しました。
const editButton = document.getElementById(editButtonId)
editButton.addEventListener("click", (event) => {
const memoId = event.currentTarget.dataset.memoId
const titleInListElement = document.getElementById("id-title-in-list-" + memoId)
const title = titleInListElement.innerText
innerText と value の違い
Inputタグの値は value で取得しますが、HTMLタグの中にセットされている値は innerText で取得する必要があります。