Create와 Read기능은 순탄하게 잘 진행이 되었는데, U, D 기능에서 문제가 생겼다.
선택된 멤버의 정보만을 업데이트 할 수 있도록 기능 구현
이건 트러블은 아니였고, 구현해야 할 기능이였으나 기록해보자면
snapshot.key 로 받아온 멤버 데이터의 고유 ID를 사용하여 접근하고 Update하면 된다고 생각했다.
데이터의 고유 ID를 한 js 파일에서 선언하고, 다른 js파일에서도 접근할 수 있도록 하고 싶었다.
변수는 파일 단위의 스코프인 전역 변수만 알고 있었는데, 이번에 브라우저 전역 객체인 window 변수를 배우게 되었다. window 객체에 변수를 추가하면, 그 변수가 브라우저에서 실행되는 모든 스크립트에 공유된다고 볼 수 있다.
나는 2개의 js 파일 내에서 memberID의 값을 공유하고자 했기에 사용하였다.
teamMate.js
window.currentMemberId = null; //멤버데이터 ID값 저장 전역변수
...
function openModal(...) {
window.currentMemberId = memberId; // 선택된 멤버의 ID 저장
...
modalScript.js
saveMember(name, mbti, blog, intro, description, imgUrl, window.currentMemberId);
이렇게 teamMate.js 에서 값을 넣어준 window.currentMemberId 변수에modalScript.js가 접근하여 값을 사용할 수 있었다.
saveMember 함수가 window.currentMemberId을 인자로 받고, 이 currentMemberId가 들어 있을 시 Update를, 비어 있을 때 Create를 하도록 했다.
const saveMember = (..., currentMemberId) => {
if (currentMemberId) {
// 수정 (memberId 있을 때)
memberFormDb.child(currentMemberId).once("value").then((snapshot) => {
const existingData = snapshot.val(); // 기존 데이터 가져오기
const updatedData = {
...
};
return memberFormDb.child(currentMemberId).update(updatedData);
}).then(() => {
console.log("멤버 정보 수정 완료");
location.reload();
}).catch((error) => {
console.log("수정 중 오류: ", error);
});
} else {
// 새로운 멤버 등록
var newMember = memberFormDb.push();
newMember.set({
...
}).then(() => {
console.log("새로운 멤버 등록 완료");
}).catch((error) => {
console.log("등록 중 오류: ", error);
});
}
};
사실 데이터의 key값을 전역변수로 뺀 거라서 보안 상의 문제가 가장 걱정이였다.
함수의 매개변수로 전달하거나,클로저 또는 모듈 패턴을 활용하는 방법이 있다고 하는데 다음에는 다르게 시도해봐야겠다. (클로저가 뭔지 아직 모름. 공부하자...)
Redux로 전역 상태 관리를 해 본 적 있지만, 이번에는 라이브러리 없이 window 객체로 전역 데이터를 관리(?)하는 방법을 새로 배웠다! (하지만 사용에 조심해야 해서 다음엔 이런 사용을 지양하고자 한다.)
멤버 카드를 작성 후, 또 새로운 카드를 작성하려고 할 때 이미지의 URL이 이전에 작성했던 이미지의 URL이 그대로 들어가는 문제
등록 후 전역변수로 사용한 imgUrl을 다시 비워주지 않아 생긴 문제로 추측되었다.
그래서, SaveMember 함수가 실행 후 imgUrl을 비우니 해결되었다.
여러개의 카드를 클릭하면, eventLisnter('click')가 중복되어 클릭한 카드를 모두 삭제해버리는 문제.
중복 이벤트 리스너 처리...를 제대로 할 줄 몰랐던 점 반성합니다. 너무 주먹구구식 코드를 짰나보다.
문제 원인:
모달을 열 때마다 addEventListener로 새로운 이벤트 리스너가 등록됨.
이전에 등록된 리스너를 제거하지 않아서 클릭할 때 중복으로 실행됨.
이것도 해결 방법이 어려운 건 아니였다.
// 오류 원인이 됐던 코드
cardDiv.addEventListener("click", (event) => {
modal_1.style.display = "flex"; // 모달 열기
// ... 모달 내용 설정 ...
});
위 코드에서는 카드가 클릭될 때마다 모달을 여는 동시에 새로운 클릭 이벤트 리스너가 추가되었다. 이로 인해 클릭 이벤트가 발생할 때마다 이전에 등록된 이벤트 리스너들이 남아 있었다.
// 수정한 코드
cardDiv.addEventListener("click", () => {
openModal(memberId, imgUrl, name, mbti, blog, intro, description, cardDiv);
});
openModal(...){
yesBtn.removeEventListener("click", handleDelete);
yesBtn.addEventListener("click", handleDelete);
}
이벤트 리스너를 중복으로 등록하지 않도록 removeEventListener를 사용하여 이전 리스너를 제거했다. 각 카드에서 클릭 이벤트가 발생할 때마다 handleDelete 함수가 중복으로 등록되는 것을 방지하고, 가독성을 높이기 위해 다음과 같이 수정했다.
이벤트 리스너가 생성되고 종료되어야 할 타이밍을 잘 파악하고... 꼭 remove하자.
삭제 알럿이 2번씩 뜬다...?
.remove() 함수에서 자체적으로 삭제되었다는 alret을 줬나보다... 근데 내가 한번 더 alret을 함. 그래서 2번 나옴. ^^
css를 잡다가 말풍선 만드는 방법을 다시 정리했다.
#menu1 {
display: none;
position: absolute;
top: 45px;
right: 17px;
background-color: white;
padding: 10px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 10px;
font-size: 14px;
display: flex;
flex-direction: column;
width: 70px; /* 원하는 너비로 조정 */
border: 1px solid #ddd; /* 회색 테두리 */
}
#menu1::after {
content: "";
position: absolute;
top: -19px; /* 삼각형 위치 조정 */
right: 21px; /* 위치 조정 */
border-width: 10px; /* 삼각형 크기 */
border-style: solid;
border-color: transparent transparent white transparent; /* 아래로 향하는 흰색 삼각형 */
display: block;
}
#menu1::before {
content: "";
position: absolute;
top: -21px; /* 회색 테두리 삼각형이 약간 더 위로 */
right: 20px; /* 위치를 흰색 삼각형과 맞춤 */
border-width: 11px; /* 회색 테두리 크기를 조금 더 크게 */
border-style: solid;
border-color: transparent transparent #ddd transparent; /* 아래로 향하는 회색 삼각형 */
display: block;
}
::after로 만들어놓은 삼각형이 이미 border을 설정해놓은 거라, 말풍선 바디 부분이랑 어떻게 같이 border을 주는거지... 하고 고민하고 있었는데
알고보니 뒤에 조금 더 큰 border color의 삼각형을 만들고 겹쳐서 border을 준 것 처럼 만드는 것이였다.
음 앞으론 더 쉽게 만들겠군.
type="file"인 input의 css는 어찌 넣는 건가. 했는데
input[type="file"] {
height: fit-content;
border:none;
}
input[type="file"]::file-selector-button {
width: 80px;
height: 30px;
background: #fff;
border: 1px solid rgb(77, 77, 77);
border-radius: 5px;
cursor: pointer;
margin-right :13px ;
}
input[type="file"]::file-selector-button:hover {
background: #212529;
color: #fff;
}
file-selector-button으로 "파일 선택" 부분 css를 잡을 수 있었다. 새로 안 사실.
css적용 본은 이러하다.
오늘 드디어 Firebase Realtime DB + Storage로 CRUD 구현을 끝마쳐 후련하다.