Notice
Recent Posts
Recent Comments
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

HYEWON JUNG의 개발일지

20231010 Til /방명록 삭제하기 & input 필수 입력값주기 본문

개발일지

20231010 Til /방명록 삭제하기 & input 필수 입력값주기

혜won 2023. 10. 11. 20:18

페이지가 거의 다 완성 되었다. 5명의 조원 중에 2명밖에 남지 않았지만 열심히 머리 모아서 만들었다. 페이지를 만들면서 대부분은 웹개발 강의에서 나왔던 부분을 고쳐서 사용했고 그 외에 스크립트 부분은 새롭게 배우면서 작성했다.

 

내가 한 양식은 폼에 입력값을 넣고 버튼을 누르면 DB에 문서 추가 되게 하기.

우선 firebase세팅을 해주고 (지금 생각안남,, 강의 보고 다시 상기시키려했지만 강의가 잘못들어와있어서,,)```

<script type = "module">

로 바꿔주고 본격적으로 버튼이 click 되었을 때 입력값이 문서에 들어가도록 해보겠다. 방명록으로 이름, 비밀번호, 내용 이렇게 넣을 것이다.

<script type = "module">

 $("selector").click(async function () {
          let name = $('#name').val();
          let comment = $('#comment').val();
            
      let doc = {
      	'name': name,   (반점 없으면 실행 안됨..)
        'comment':comment
      };
      await addDoc(collection(db, "데이터베이스의 컬렉션 이름"), doc);
	---문서 추가 후 새로고침---
      alert('반가워요!')
      window.location.reload();
      })
      </script>

 

$('  ').val(); 은 '  '안의 값의 value를 뜻하는데 지근은 아래의 input 태그에서 id로 설정된 것들을 정의했다. 

window.location.reload();는 자동으로 새로고침

 

이렇게 addDoc을 해준 뒤 특정 양식으로 다시 getDoc을 

let docs = await getDocs(collection(db, "데이터베이스 컬렉션 이름"));
        docs.forEach((doc) => {
            let row = doc.data();
            let name = row['name'];
            let comment = row['comment'];

            let temp_html = `
                <div class="col">
                    <div class="card h-100">
                        <div class="postData card-body" data-id="${doc.id}">
                        <h5 class="card-title">${name}</h5>
                        <p class="card-text">${comment}</p>
                            
                        </div>
                    </div>
                </div>`;

            $('#card').append(temp_html);

        });

이렇게 Doc에서 값을 가져와서 카드로 나타나게 만들었다. 

여기까진 쉬운 문제 였지만 방명록을 삭제할 수 있게 하자란 팀원분의 말에 우리는 다시 연구에 들어갔다. 

 

삭제를 위해 우리가 필요한 것은 

- 작성폼에 비밀번호 입력란 추가하기

- 카드에 삭제버튼 추가하기

- 비밀번호 입력할 곳  만들기 

- 입력된 비밀번호 DB에 추가하기

- DB의 값과 새로 입력된 비밀번호가 같은지 확인하는 조건문 쓰기

 

정도를 생각했다.

 

우선 난 틀부터 만들자고 생각해서 추가해야할 태그들을 만들었다.

let temp_html = `
                <div class="col">
                    <div class="card h-100">
                        <div class="postData card-body" data-id="${doc.id}">
                        <h5 class="card-title">${name}</h5>
                        <p class="card-text">${comment}</p>
          --->                  <div class="dbutton" class="d-grid gap-2 d-md-flex justify-content-md-end">
          --->                  <button class="deleteBtn btn btn-outline-success me-md-2 btn-sm" type="button">삭제</button>
                            </div>
                        </div>
                    </div>
                </div>`;

            $('#card').append(temp_html);

카드에 삭제버튼을 추가해줬고 

           </div>
            <div class="col-md">
                <div class="form-floating">
                    <input type="password" class="form-control" id="pass" placeholder="비밀번호" maxlength="6">
                    <label for="floatingInputGrid">비밀번호를 입력하세요</label>
                </div>
            </div>
        </div>

폼에 비밀번호 구역을 만들었다.  input type을 passward로 하면 자동으로 바로 보이지 않돌고 된다. 

 

이제 비밀번호 입력값을 DB에 넣는데 

<script type = "module">

 $("selector").click(async function () {
          let name = $('#name').val();
          let pass =$('#pass').val();
          let comment = $('#comment').val();
          
            
      let doc = {
      	'name': name,
        'pass': pass,		(반점 없으면 실행 안됨..)
        'comment':comment
      };

똑같이 대입해서 입력해줬다.  그리고 이제 DB에서 값을 가져왔다. 이런식으로(이렇게만 하면 안됨..)

 let docs = await getDocs(collection(db, "firstteam"));
        docs.forEach((doc) => {
            let row = doc.data();
            let name = row['name'];
            let comment = row['comment'];
            let pass = row['pass'];

그리고 

let pass =${'#pass'} 해서 input값을 가져와서

console.log("test",pass);

console.log("pass",pass);

 이런 식으로 했더니 게속 DB의 값이 잡히지 않았다. 구글링 해서 별의 별 방법을 써도 undefined가 뜨거나 아예오류가 나거나 빈칸으로 남아있었다. 

 

알고보니 우리가 빈칸으로 떴을 때는 방명록 폼에 입력되어있는 값을 잡아온 것이거나 아예 잡히지 않은 것이었고 우선적으로 잡으려고 한다면. temp_html에 pass가 찍히게는 하되 보이지는 않게 하라는 튜터님의 말을 따라 

let temp_html = `
                <div class="col">
                    <div class="card h-100">
                        <div class="postData card-body" data-id="${doc.id}">
                        <h5 class="card-title">${name}</h5>
                        <p class="card-text">${comment}</p>
                        <p class="del" id="del">${pass}</p>
                            <div class="dbutton" class="d-grid gap-2 d-md-flex justify-content-md-end">
                            <button class="deleteBtn btn btn-outline-success me-md-2 btn-sm" type="button">삭제</button>
                            </div>
                        </div>
                    </div>
                </div>`;

이런식으로  추가한 후에 

            $(".del").hide();

hide를 써서 숨겨주었다. 

 

그리고 비밀번호를 입력할 수 있는 곳은 prompt를 이용해서 만들었다. 

 

아무튼 이런저런 방법을 사용하다 결국 튜터님을 또 찾아갔다. 

 

우리의 설명을 들은 튜터님은 결국 우리에게 뼈대를 만들어 주셨다. 

$("#card").on("click", ".deleteBtn", async function () {
            const inputPassword = prompt("패스워드를 입력해주세요.");

            const cardElement =$ (this).closest(".card-body");
            const storedPassword = cardElement.find("#del").text();

            console.log("storedPassword", storedPassword);
            console.log("inputPassword", inputPassword);

            if (storedPassword == inputPassword) {
                // 삭제처리
                alert("성공적으로 삭제되었습니다.");
    
            } else {
                // 오류!
                alert("비밀번호가 일치하지 않습니다.");
            }
        });

이런식으로 바꿔서 주셨다. 솔직히 설명은 이해가 갔지만 응용을 할 수 있을 진.. 모르겠다. 

////우선 $('#card').on( "click","버튼 이름", async function(){ 이런 문법을 처음본다!!

정말 다양한 문법이 있구나 느낀다. . 

 

이제 둘이서 삭제를 구현해야한다.  삭제를 구현하려면 필요한 것이

- 삭제할 카드 지정하기 

- 삭제하기

우선 doc에서 문서를 끌고 오는 것을 했다. 

let docs = await getDocs(collection(db, "firstteam"));
        docs.forEach((doc) => {
            let row = doc.data();
            let name = row['name'];
            let comment = row['comment'];
            let pass = row['pass'];
            let docId = doc.id;

            let temp_html = `
                <div class="col">
                    <div class="card h-100">
                        <div class="postData card-body" data-id="${doc.id}">   <----얜 뭘까
                        <h5 class="card-title">${name}</h5>
                        <p class="card-text">${comment}</p>
                        <p class="del" id="del">${pass}</p>
                        <p class="del" id="delid">${docId}</p>
                            <div class="dbutton" class="d-grid gap-2 d-md-flex justify-content-md-end">
                            <button class="deleteBtn btn btn-outline-success me-md-2 btn-sm" type="button">삭제</button>
                            </div>
                        </div>
                    </div>
                </div>`;

            $('#card').append(temp_html);
            $(".del").hide();

중간에 튜터님이 오셔서  deleteDoc이란 것이 있으니 참고하라고 했다.  그대로 구글링을 했더니 firebase의 공식 문서가 나왔다.

 

https://firebase.google.com/docs/firestore/manage-data/delete-data?hl=ko

 

Cloud Firestore에서 데이터 삭제  |  Firebase

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 Cloud Firestore에서 데이터 삭제 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세

firebase.google.com

import { doc, deleteDoc } from "firebase/firestore";

await deleteDoc(doc(db, "cities", "DC"));

그대로 따와서 조건문 위에 붙였는데 계속 import랑 await 가 오류가 났다.  deleteDoc에 들어있는 값들을 바꿔줬다.

await deleteDoc(doc(db, "컬렉션 이름", "문서이름")); 바꿔줘도 값은 똑같았다.  console로 해도 값이 끌려오지 않았다. 그래서 튜터님을 또 찾아갔고 import의 자리를 알아냈다. 그리고 await를 쓸 때의 유의점을 알려주셨다. 

 

import의 경우 위에 firebase세팅을 할 때 import 무리가 있었는데 그것들과 같이 쓰면 된다고 알려주셨고 await의 경우 그냥  쓰는게 아니라 function에 async을 꼭 넣어줘야한다고 말씀해주셨다. 더 자세하게는 javascript를 배울 때 알아가면된다고 하셨다. 그리고 다른 사이트를 알려주셨는데

https://softauthor.com/firebase-firestore-delete-document-deletedoc/

 

Firebase V9 Firestore DELETE Document Using deleteDoc()

Learn how to delete a document from a collection in Firebase version 9 Cloud Firestore using the deleteDoc() method.

softauthor.com

 

그렇게  돌아와서 다시 손을 보는데도 잘 되지 않았다. 여전히 정보가 끌어와지지 않았다. 나중에 알고보니 import를 완전히 잘못하고 있었다 .  중복된 부분이 있었다. 그리고 우리가 가져온 것은from 뒤가 url이 아니었는데 아래와 같이 되었어야하는 것이다.  그래서 위에 중복된 부분에 doc, deleteDoc을 추가해서 진행했다.

import { getFirestore, doc, deleteDoc } from "https:/

그 뒤로는 다시 연구해보며 하는데 많은 도움 끝에 해냈다.

 const delpass = cardElement.find("#delid").text();

            const docRef = doc(db, "firstteam", delpass);


            if (storedPassword == inputPassword) {
                // 삭제처리
                alert("성공적으로 삭제되었습니다.");
                await deleteDoc(docRef);
                window.location.reload();

            } else {
                // 오류!
                alert("비밀번호가 일치하지 않습니다.");
            }
        });

문서의 이름을 비밀번호 같이 카드에 넣고 숨겨준다음에 id값을 줘서 새롭게 정의를 해주었다. 그런다음에 문서이름을 넣었던 곳에 delpass를 넣어줬더니 잘 되었다. 

 

삭제를 구현한 뒤에 input에 필수입력값을 주기로 했는데  구글링을 해보니 required를 이용하면 된다길래 바로 적용을 해봤다. 

<form>안에 넣고 required를 적어줬는데 내가 원하는 대로가 아니라 그냥 빈칸이면 "입력해야한다~" 이런 멘트만 뜨지 액션을 멈추는 것은 아니라서 빈칸으로도 저장이 되고 있었다. 

 

그래서 이번에도 튜터님을 찾아갔다. 

$("#postingbtn").click(async function () {
            let name = $('#name').val();
            if (name === '') {
                alert('성함을 입력해주세요!')
                return;
            }
            let pass = $('#pass').val();
                if (pass === '') {
                alert('비밀번호를 입력해주세요!')
                return;
            }
                let comment = $('#comment').val();
                if (comment === '') {
                alert('내용을 입력해주세요!')
                return;
            }
                
                let doc = {
                    'name': name,
                    'comment': comment,
                    'pass': pass

                };
                await addDoc(collection(db, "firstteam"), doc);

            alert('반가워요!')
            window.location.reload();

        })

이건 완성본인데 사실 구글링을 하다가 블로그에서 비슷한 식을 발견 했었는데

<script>

	var name = document.getElementById("name").value;
	
	if(name==''){
		alert("이름을 입력해주십시오.");
		$('#name').focus();
		return false;
	}
	
</script>

같은 의미 였는데 위치가 달라서 실행이 되지 않았던 것을.. 

처음엔 위치를 addDoc의 밑에 뒀었는데 확인들이 addDoc이 되기 전에 되야하는데 밑에 있어서 그냥 다 들어가버리더라.. 그래서 addDoc전에 실행되게 했더니 완료~!

 

아직은 솔직히 잘 모르겠지만 하나는 알겠다. 남들보다 더 노력해야 한다는 것을.. 

 

이번에 좀 더 구현해 보고 싶은 것은 

1. 클릭하면 해당파트로 이동하는 것

2. 상단으로 올라가기

3. css좀더 예쁘게.