• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 JavaScript, TS 게시판 웹개발 기능대회 문의합니다.

웹개발 기능대회 문의합니다.

4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 글쓴이
  • #94089

    동둥당
    참가자
    안녕하세요, 저는 자바스크립트로 진행하고 있는데 도저히 모르겠어서 
    질문드립니다.
    
    검색기능과 진열기능은 일단 작동이 됩니다. 
    이제 담기버튼과 드래그&드롭을 하는데  
    Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
    이런말이 계속 나오고 
    드래그&드롭에서는 dataset.id를 들어가면 id가 나오질 않네요.
    선생님 답에는 dataset.id이 들어가있는걸 확인했습니다.
    
    검색을 해보니
    에러 원인이 HTML이 모두 로드 되기 전에 자바스크립트 영역에서 HTML을 참조하기 때문이라 하더라구요.
    그래서 의심이 가는 부분이 js파트에서 백틱으로 친 부분들에게 있다고 생각을 했습니다.
    그래서 답을 보니 제이쿼리는 가능한거 같더라구요. 자바스크립트 답안지가 있다면 좋겠지만 
    없는거 같아서 질문 남깁니다 ㅠㅠ 
    제가 어디서부터 잘못된건지 짚어주시면 다시 도전해보겠습니다. 
    많은 가르침 부탁드려요ㅜ
     
    
    
    ________________________________________________________________
    
    HTML
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
    href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
    rel="stylesheet"
    integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"
    crossorigin="anonymous"
     />
    <link rel="stylesheet" href="./index.css" />
    <title>Document</title>
    </head>
    <body>
    <!-- nav -->
    <nav class="navbar navbar-expand-md navbar-dark bg-dark">
    <div class="container-fluid">
    집꾸미기
    <div class="collapse navbar-collapse" id="navbarCollapse">
    <ul class="navbar-nav me-auto mb-2 mb-md-0">
    <li class="nav-item">
    Home

    <li class="nav-item"> 스토어

    <li class="nav-item"> 시공견적

    </div> </div> </nav> <!-- 검색어 창 --> <div class="container"> <div class="row"> <form class="d-flex mt-3 col-2" role="search"> <input class="form-control me-2" type="search" placeholder="검색어 입력" aria-label="Search" /> </form> </div> </div> <!-- 카드들 모음 --> <div class="container"> <div class="row cards drag-img"></div> </div>

    <!-- 장바구니 -->
    <div class="container basket-wrap" style="background: #e2e2e2">
    <h4>장바구니 (드래그 가능)</h4>
    <div class="row basket"></div>
    </div>
     <script
    src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz"
    crossorigin="anonymous"
     ></script>
     <script src="./index.js"></script>
    </body>
    </html>

    ________________________________________________________________

    CSS
    
    
    * {
    margin: 0;
    box-sizing: border-box;
    }
    .basket {
    min-height: 300px;
    width: 100%;
    background: black;
    padding: 0px;
    }
    .basket-wrap {
    padding: 30px;
    margin-top: 30px;
    }

    ________________________________________________________________

    JS
    
    
    const input = document.querySelector(".form-control");
    const cards = document.querySelector(".cards");
    // 상품 보여주기
    let products = [];
    fetch("./store.json")
    .then((res) => res.json())
    .then((data) => {
    // 원본데이터 다른데서 많이 쓰니까 변수에 보관
    products = data.products;
    // 페이지로드시 json 데이터 가져와서 메인페이지 내용 만들기
    data.products.forEach((a, i) => {
    let 템플릿 = `
     <div class="col-sm-3 mt-3 " data-id=${a.id}>
     <div class="item" draggable="true" >
     < img src="${a.photo}" class="w-100">
     <h5>${a.title}</h5>
     <h6>${a.brand}</h6>
     <p>가격 : ${products[i].price}</p>
     <button class="add" data-id="${a.id}">담기</button>
     </div>
     </div>`;
    console.log(`${a.id}`);
    cards.insertAdjacentHTML("beforeend", 템플릿);
    });
    });
    input.addEventListener("change", (e) => {
    let 검색어 = e.target.value;
    // 지금 입력한 글자가 제목에 있으면 let products에서 검색어 있는것만 남기기
    let newProducts = products.filter((a) => {
    return a.title.includes(검색어) || a.brand.includes(검색어);
    });
    // 카드 초기화 시키기
    cards.innerHTML = "";
    // 검색한 결과로 카드 나타내주기
    newProducts.forEach((a, i) => {
    let 템플릿 = `
     <div class="col-sm-3 mt-3 ">
     <div class="" draggable="true">
     < img src="${a.photo}" class="w-100">
     <h5>${a.title}</h5>
     <h6>${a.brand}</h6>
     <p>가격 : ${products[i].price}</p>
     <button class="add" data-id="${a.id}">담기</button>
     </div>
     </div>`;
    cards.insertAdjacentHTML("beforeend", 템플릿);
    });
    });
    // 담기버튼 누르기
    let add = document.querySelector(".add");
    add.addEventListener("click", () => {
    console.log("담기");
    });
    // 드래그 이벤트
    let item = document.querySelector(".item");
    const basket = document.querySelector(".basket");
    let cardNumber = 0;
    // 드래그 이벤트 발생요소
    item.addEventListener("dragstart", function (e) {
    console.log(e);
    });
    basket.addEventListener("dragover", (e) => {
    e.preventDefault();
    });
    basket.addEventListener("drop", (e) => {
    let productId = e.dataTransfer.getData("id");
    console.log(productId);
    });
    
    
    		
    	
    #94107

    codingapple
    키 마스터
    이벤트리스너들을 data.products.forEach() 바로 다음줄로 옮깁시다
    #94621

    동둥당
    참가자
    선생님 
    우선 담아지기 한개 가능,
    총 가격은 나옵니다. 
    
    1. 첫번째 상품인 식기세척기를 드래그 했을때 
    e.target.dataset.id가  undefined으로 나옵니다. 이벤트리스너들을 data.products.forEach() 바로 다음줄에 옮기라고 하셨는데
    순서대로 나열한거 같은데 나오질 않아서 모르겠습니다..고민을 많이했는데도 이 부분은 모르겠습니다.
    2. 담기버튼과 드래그를 할때 한개만 작동이 됩니다. 
    
    담기버튼을 누를때 첫번째꺼만 누르면 잘 담기고 가격도 잘 나옵니다. 
    그러나 여러개 상품이 있으니 let add = document.querySelectorAll(".add"); 이렇게 해준뒤 누르려고 하면
    index.js:36 Uncaught (in promise) TypeError: add.addEventListener is not a function
    at index.js:36:9 라고 뜨네요. 
    add[1].addeventlistener라고 하면 다른 것들도 담아집니다. 
    제이쿼리랑 자바스크립트의 차이로 제가 잘 모르는것인지 궁굼합니다. 혹은  모든 버튼이 동작하려면
    forEach함수를 사용해야 하는 것일까요? 
    
    _______________________________________________________________________
    HTML 
    
    <!-- nav -->
    <nav class="navbar navbar-expand-md navbar-dark bg-dark">
    <div class="container-fluid">
    집꾸미기
    <div class="collapse navbar-collapse" id="navbarCollapse">
    <ul class="navbar-nav me-auto mb-2 mb-md-0">
    <li class="nav-item">
    Home

    <li class="nav-item"> 스토어

    <li class="nav-item"> 시공견적

    </div> </div> </nav> <!-- 검색어 창 --> <div class="container"> <div class="row"> <form class="d-flex mt-3 col-2" role="search"> <input class="form-control me-2" type="search" placeholder="검색어 입력" aria-label="Search" /> </form> </div> </div> <!-- 카드들 모음 --> <div class="container"> <div class="row cards drag-img"></div> </div>

    <!-- 장바구니 -->
    <div class="container basket-wrap" style="background: #e2e2e2">
    <h4>장바구니 (드래그 가능)</h4>
    <div class="row basket"></div>
    </div>
    <!-- 가격 -->
    <div class="container my-3">
    <h4>최종가격</h4>
    <p class="final-price"></p>
    <button class="buy">구매하기</button>
    </div>
    <!-- 모달 -->
    <div class="modal1" style="display: none">
    <div class="white-bg">
    <h4>성함</h4>
    <input type="text" id="name" />
    <h4>연락처</h4>
    <input type="text" id="phone" />
    <button class="show-receipt">입력완료</button>
    <div>
    <button class="close">닫기</button>
    </div>
    </div>
    </div>
    <!-- 영수증 모달 -->
    <div class="modal2" style="display: none">
    <div class="white-bg">
    <h4>영수증</h4>
    <canvas id="canvas" width="350" height="350"></canvas>
    <div>
    <button class="close">닫기</button>
    </div>
    </div>
    </div>
    
    
    _______________________________________________________________________
    CSS
    
    
    * {
    margin: 0;
    box-sizing: border-box;
    }
    .basket {
    min-height: 300px;
    width: 100%;
    background: black;
    padding: 0px;
    }
    .basket-wrap {
    padding: 30px;
    margin-top: 30px;
    }
    .basket div {
    padding: 15px;
    border-radius: 5px;
    }
    .item {
    background: white;
    padding: 20px;
    margin-top: 20px;
    }
    _______________________________________________________________________
    JS
    
    
    const input = document.querySelector(".form-control");
    const cards = document.querySelector(".cards");
    const final = document.querySelector(".final-price");
    let add = document.querySelector(".add");
    // 상품 보여주기
    let products = [];
    let cart = [];
    fetch("./store.json")
    .then((res) => res.json())
    .then((data) => {
    // 원본데이터 다른데서 많이 쓰니까 변수에 보관
    products = data.products;
    // 페이지로드시 json 데이터 가져와서 메인페이지 내용 만들기
    data.products.forEach((a, i) => {
    let 템플릿 = `
     <div class="col-sm-3 mt-3 " data-id=${a.id}>
     <div class="item" draggable="true" >
     < img src="${a.photo}" class="w-100">
     <h5>${a.title}</h5>
     <h6>${a.brand}</h6>
     <p>가격 : ${products[i].price}</p>
     <button class="add" data-id="${a.id}">담기</button>
     </div>
     </div>`;
    cards.insertAdjacentHTML("beforeend", 템플릿);
    });
    // 담기버튼 누르기
    let add = document.querySelector(".add");
    add.addEventListener("click", (e) => {
    //지금 누른 상품번호
    let productId = e.target.dataset.id;
    console.log(productId);
    //담기버튼 누를때 let cart = []에 상품을 {} 형태로 보관부터 하고
    //let cart에 상품이 이미있는지 찾고,없으면 let cart에 {}추가, 있으면 수량만 ++;
    let 몇번째 = cart.findIndex((a) => {
    return a.id == productId;
    });
    if (몇번째 == -1) {
    let 현재상품 = products.find((a) => {
    return a.id == productId;
    });
    현재상품.count = 1;
    cart.push(현재상품);
    } else {
    cart[몇번째].count++;
    }
    // 담기버튼 누를 때 마다 장바구니 박스에 let cart 안에 있던{} 갯수만큼 html 생성
    basket.innerHTML = "";
    cart.forEach((a, i) => {
    let 템플릿 = `
     <div class="col-sm-3 mt-3">
     <div class="item">
     < img src="${a.photo}" class="w-100">
     <h5>${a.title}</h5>
     <h6>${a.brand}</h6>
     <p class='item-price'> ${products[i].price}</p>
     <input type='number' value='${a.count}' class='item-count w-100' />
     </div>
     </div>`;
    basket.insertAdjacentHTML("beforeend", 템플릿);
    console.log(a.count);
    });
    // 총가격 계산해서 표기해주는 기능
    가격계산();
    //input값 조절해도 총가격 계산해서 표기해줘야될듯
    const itemCount = document.querySelector(".item-count");
    itemCount.addEventListener("input", () => {
    가격계산();
    });
    }); // add버튼 끝
    // 드래그 이벤트
    let item = document.querySelector(".item");
    let basket = document.querySelector(".basket");
    // 드래그 이벤트 발생요소
    item.addEventListener("dragstart", function (e) {
    console.log(e);
    });
    basket.addEventListener("dragover", (e) => {
    e.preventDefault();
    });
    basket.addEventListener("drop", (e) => {
    let productId = e.dataTransfer.getData("id");
    });
    });
    // 총 가격 계산해서 표기해주는 기능
    function 가격계산() {
    let finalPrice = 0;
    const itemCount = document.querySelectorAll(".item-count");
    const itemPrice = document.querySelectorAll(".item-price");
    for (let i = 0; i < itemCount.length; i++) {
    let price = itemPrice[i].innerText;
    let count = itemCount[i].value;
    finalPrice += parseFloat(price * count);
    }
    console.log(finalPrice);
    final.innerHTML = finalPrice;
    }
    input.addEventListener("change", (e) => {
    let 검색어 = e.target.value;
    // 지금 입력한 글자가 제목에 있으면 let products에서 검색어 있는것만 남기기
    let newProducts = products.filter((a) => {
    return a.title.includes(검색어) || a.brand.includes(검색어);
    });
    // 카드 초기화 시키기
    cards.innerHTML = "";
    // 검색한 결과로 카드 나타내주기
    newProducts.forEach((a, i) => {
    let 템플릿 = `
     <div class="col-sm-3 mt-3 ">
     <div class="" draggable="true">
     < img src="${a.photo}" class="w-100">
     <h5>${a.title}</h5>
     <h6>${a.brand}</h6>
     <p>가격 : ${products[i].price}</p>
     <button class="add" data-id="${a.id}">담기</button>
     </div>
     </div>`;
    cards.insertAdjacentHTML("beforeend", 템플릿);
    });
    });
    
    
    
    
    #94650

    codingapple
    키 마스터
    .add 달린 버튼은 여러개인데 지금은 첫째 .add 버튼에만 이벤트리스너 붙인듯요
    querySelectorAll로 찾은건 뒤에 [] 붙여서 씁시다
4 글 보임 - 1 에서 4 까지 (총 4 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠