이전에 만들어뒀던 댓글 생성하는 기능에 이어 수정 및 삭제 기능도 추가로 구현해야 했다. 처음에는 댓글을 삭제하고 수정하는 함수를 어디에 넣어야할지 잘 가늠이 되지 않았는데, 튜터님께 조언을 구해 로직을 이해할 수 있었다.
결국 댓글을 생성할 때 삭제되거나 수정된 댓글을 반영해 화면에 그려줘야하기 때문에 generateComment
함수 안에서 이 모든 것이 이뤄져야한다는 것을 알게 됐다. 여기서 함수 이름을 generate으로 적어두어서 자꾸 헷갈리는 부분이 있었는데, 이런 로직이라면 paintComment
가 더 적합하다고 생각했다. 함수 이름 짓기의 중요성을 다시 한 번 깨닫게 됐다.
초기 코드는 댓글 수정 및 삭제 시 프롬프트 창을 띄워 비밀번호와 수정할 내용을 입력하는 방식이었는데, 모달창을 띄우자는 아이디어를 내어 다른 팀원분이 모달창으로 수정해서 구현해주셨다.
댓글 수정 와이어프레임 제안
display : hidden;
으로 가려두고 해당 자리에 새로운 인풋 댓글수정창 넣기// 로컬스토리지 데이터 불러오기
function loadComments(movieId) {
const comments = getComments(movieId);
generateComment(comments);
}
// 로컬스토리지에 데이터 저장하기
function saveComments(movieId, comments) {
localStorage.setItem(`comments_${movieId}`, JSON.stringify(comments));
}
//로컬스토리지에서 데이터 가져오기
function getComments(movieId) {
const savedComments = localStorage.getItem(`comments_${movieId}`);
return savedComments ? JSON.parse(savedComments) : [];
}
초기에 시도한 삭제 시 구현하려고 했던 로직은 기존의 저장된 데이터 배열을 forEach
로 돌면서 클릭 이벤트가 적용된 요소의 아이디와 삭제한 요소의 아이디값을 확인해주는 것이었다. 새로운 배열을 선언하고 지워지지 않은 나머지 요소들을 새로운 배열에 넣어주어, 다시 그 배열을 setItem
을 통해 localStorage
에 넣어주려 했다.
function deleteComment() {
// 화면에서 댓글 지워주기
const li =
event.target.parentElement.parentElement.parentElement.parentElement;
li.remove();
//로컬스토리지에서 데이터 지워주기
const deletedId = 124; // 랜덤 아이디 부여 가정
const newComments = [];
localStorage.getItem("comments").forEach(element => {
if (element.id !== deletedId) {
newComments.push(element)
}
});
localStorage.setItem("comments", newComments)
}
삭제는 잘 되었지만 새로고침 시 로컬스토리지에 있는 데이터가 원하는대로 업데이트되지 않았고 push
를 통해 넣어줄 경우, forEach
를 돌아가면서 배열에 push
를 해줄 경우 원하는 순서대로 들어가지 않을 것이라 판단해서 방식을 바꿔filter
를 사용하기로 했다.
// getComments함수를 통해 받아온 데이터의 배열
let commentDrawn = getComments(movieId, comments);
//댓글 삭제하기 (모달 수정)
const modal = document.getElementById("delmodal");
const confirmBtn = document.getElementById("delconfirmBtn");
const passwordInput = document.getElementById("delpasswordInput");
const deleteComment = (event) => {
// 모달창 닫기
const closeModal = () => {
modal.style.display = "none";
passwordInput.value = "";
commentInput.value = "";
};
const li =
event.target.parentElement.parentElement.parentElement.parentElement;
commentDrawn.forEach((element) => {
let cancelSwitch = Boolean;
if (li.getAttribute("id") === String(element.Id)) {
modal.style.display = "block";
confirmBtn.onclick = () => {
const passwordTry = passwordInput.value;
if (passwordTry === element.Password) {
cancelSwitch = true;
li.remove();
const newComments = commentDrawn.filter(
(element) => element.Id !== li.getAttribute("id")
);
saveComments(movieId, newComments);
alert("삭제되었습니다.");
passwordInput.value = "";
location.reload();
} else {
cancelSwitch = false;
passwordInput.value = "";
alert("비밀번호가 틀렸습니다. 다시 입력해주세요.");
}
modal.style.display = "none";
};
modal.querySelector(".close").onclick = () => {
modal.style.display = "none";
cancelSwitch = false;
};
}
});
// 모달 외부 클릭 시 닫기
window.onclick = (event) => {
if (event.target === modal) {
closeModal(); // 모달 닫기
}
};
};
const deleteBtn = document.querySelectorAll(".delete");
deleteBtn.forEach((element) =>
element.addEventListener("click", deleteComment)
);
const newComments = commentDrawn.filter( (element) => element.Id !== li.getAttribute("id") );
filter로 기존의 배열에서 삭제된 요소를 제외한 나머지를 새로운 newComments 배열을 만들어주고,
saveComments(movieId, newComments)
로 새로운 배열을 다시 로컬스토리지에 저장해줘 데이터를 업데이트해준다.
// 댓글 수정 (모달 수정)
const editComment = (e) => {
const commentBox = e.target.parentNode.parentNode.parentNode.parentNode;
const modal = document.getElementById("modal");
const passwordInput = document.getElementById("passwordInput");
const commentInput = document.getElementById("commentInput");
const submitBtn = document.getElementById("submitBtn");
const cancelBtn = document.getElementById("cancelBtn");
modal.style.display = "block"; // 모달창 열기
// 모달창 닫기
const closeModal = () => {
modal.style.display = "none";
passwordInput.value = "";
commentInput.value = "";
};
// 확인 버튼 클릭 시
submitBtn.onclick = () => {
const passwordEditTry = passwordInput.value;
commentDrawn.forEach((element) => {
if (commentBox.getAttribute("id") === String(element.Id)) {
if (passwordEditTry === element.Password) {
element.Review = commentInput.value;
saveComments(movieId, commentDrawn);
alert("저장되었습니다.");
closeModal(); // 모달 닫기
location.reload(); // 페이지 새로고침
} else {
alert("비밀번호가 일치하지 않습니다.");
closeModal(); // 모달 닫기
}
}
});
};
// 취소 버튼 클릭 시
cancelBtn.onclick = () => {
closeModal(); // 모달 닫기
};
// 모달 외부 클릭 시 닫기
window.onclick = (event) => {
if (event.target === modal) {
closeModal(); // 모달 닫기
}
};
};
const editBtn = document.querySelectorAll(".edit");
editBtn.forEach((element) => element.addEventListener("click", editComment));
댓글을 수정할 때는 로컬스토리지의 value에 있는 객체와 배열은 그대로 유지되면서 내용만 업데이트해주는 것이기 때문에
element.Review = commentInput.value;
로 input.value만 변경해 내용을 업데이트 해주고 이 값이 있는 기존 배열을 다시
saveComments(movieId, commentDrawn);
를 통해 로컬스토리지에 저장해줬다.