Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
관리 메뉴

게으른 완벽주의자의 개발자 도전기

[shop]장바구니에서 구매하기 버튼 클릭하여 구매하기(closest, parentElement) 본문

Js

[shop]장바구니에서 구매하기 버튼 클릭하여 구매하기(closest, parentElement)

머리방울 2022. 8. 29. 00:37

<사진출처 yes24>

 

장바구니에서 체크박스를 이용하여 선택구매를 클릭했을 때

1) 구매하기 진행 2) 구매이력 남기기 3) 장바구니에서 해당 상품 삭제를 진행하고자 한다.

상세페이지에서 구매하기 버튼 클릭과 다른점은 한가지 상품이 아닌

다양한 상품을 한 번에 구매한다는 점이다.

 

1. mapper 쿼리 작성

1) 구매하기

<insert id="cartBuy">
INSERT INTO SHOP_BUY(
MEM_ID
, BUY_CODE
, TOTAL_PRICE
) VALUES (
#{memId}
, #{buyCode}
, #{totalPrice} 
)

</insert>

 

2)구매이력

구매이력에서는 무슨 상품을 샀는지 내역이 들어간다.

이때 내역에는 상품코드, 가격, 이름 등등의 다양한 정보가 들어간다.

이런 정보를 한 번에 넣을 수 있는 것이 List이다.

BuyDTO에 List<BuyDetailDTO> buyDetailList 만들고, getter와 setter를 만든다

 

<insert id="insertCartDetail">
INSERT INTO BUY_DETAIL
(BUY_DETAIL_CODE
, ITEM_CODE
, BUY_CNT
, BUY_CODE
) 


buyDTO.getBuyDetailList()가 실행될 수 있게 컬렉션을 사용하겠다.
<foreach collection="buyDetailList" item="buyDetailDTO" separator="UNION ALL" index="i"> 

(buyDetailList에서 하나를 꺼냈을 때 buyDetailDTO라고 할 것이고

하나의 쿼리가 끝나면 UNION ALL로 연결할 것이고, 인덱스를 사용할 것이다)

★SELECT문에 |LPAD(#{i}+1, 2, 0)로 인덱스를 추가한 이유는

쿼리가 끝나면 UNION ALL로 연결되기 때문에 인덱스를 추가하지 않으면

BUY_DETAIL_CODE는 계속 같은 수로 머무르게 된다.

즉, SELECT |LPAD(#{1, 2, 0) FROM DUAL 

UNION ALL

SELECT |LPAD(#{1, 2, 0) FROM DUAL

첫번째 SELECT문에서도 1 두번째 SELECT 문에서도 1이 나오게 되는 것이다.

그래서 인덱스로 LPAD(#{i}+1 1, 2, 3 순차적으로 나오게 만든 것이다.



SELECT #{buyDetailDTO.buyDetailCode} ||'_'||LPAD(#{i}+1, 2, 0) (두자리만 나온다는 가정 )
, #{buyDetailDTO.itemCode}
, #{buyDetailDTO.buyCnt}
, #{buyDetailDTO.buyCode} 
FROM DUAL
</foreach>
</insert>

 

3) BUY_CODE 조회 

<select id="selectBuyCode" resultType="String">
SELECT 'BUY_' || LPAD(NVL(MAX(TO_NUMBER(SUBSTR(BUY_CODE,5))),0)+1, 3, 0) 
FROM SHOP_BUY
</select>

 

4) 상품 장바구니에서 삭제

장바구니에는 CART_CODE가 하나가 아닌 여러개가 있다.

이때 사용할 수 있는 것이 LIST이다. 

cartDTO에 LIST<String>cartCodeList를 만들고,

getter와 setter를 만들어준다.(cartCode 하나를 출력하기에 변수String)

 

또한, in(A, B, C)를 활용해서 충족되는 데이터만 삭제하도록 한다.

 

<delete id="deleteCarts">
DELETE SHOP_CART 
WHERE CART_CODE IN
<foreach collection="cartCodeList" item="cartCode" open="(" close=")" separator=", ">
#{cartCode}
</foreach>
</delete>

2.인터페이스 메소드 작성

세가지 작업의 트랜잭션이 완벽하게 수행되면 커밋하도록 설정하였다.

 

@Override
public void cartBuy(BuyDTO buy, CartDTO cart) {

try {
장바구니 구매하기
sqlSession.insert("buyMapper.cartBuy", buy);
구매이력
sqlSession.insert("buyMapper.insertCartDetail", buy);
구매한 상품은 장바구니에서 삭제
sqlSession.delete("cartMapper.deleteCarts", cart);

// 커밋

sqlSession.commit();

} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
}
}

 

3. JS

1) jsp

<td><input data-cart-code ="bbb" 

data-cartcode="${cart.cartCode }"

 type="checkbox" class="chk" value="${cart.itemCode}"></td>



<form action="insertBuys.buy" method="post">
( name=자바로 데이터 가져갈려고 id= js에서 쓸려고)
<input type="hidden" id="totalPrice" value="" name="totalPrice">
<input type="hidden" id="itemCode" value="" name="itemCode">
<input type="hidden" id="buyCnt" value="" name="buyCnt">
<input type="hidden" id="cartCode" value="" name="cartCode">
</form>
<input type="button" value="선택구매" onclick="goBuy();">

 

2) JS

i) 데이터 위치 지정하기

 

아래와 같은 boardList가 있다고 생각하자

<tr>

     <td>첫번째 메뉴</td> 

     <td>두번째 메뉴</td>

     <td> 세번째 메뉴</td>

     <td>네번째 메뉴</td>

     <td> 다섯번째 메뉴</td>

</tr>



1) parentElement 사용하기


첫번째 메뉴라는 문자열의 부모태그는 <td>이다.

- >  boardList.parentElement
<td>의 부모인 <tr>로 가고자 한다. 

- > boardList.parentElement.parentElement
- children[ ] : 자식태그(배열) 
- previousElementSibling : 이전 형제(같은 <td>)
- nextElementSibling : 다음 형제 찾아감 (<td>)

5번째 자식인 다섯번째 메뉴 찾기 (배열은 0이 1이니까)
boardList.parentElement.parentElement.children[4].innerText

-> tr 입장에서 td들은 자식이기 때문에 td의 다섯번째 자식(children[4])



2) closest

closest() : 가장 가까운 상위 태그를 찾아 감



5번째 자식인 다섯번째 메뉴 찾기
boardList.closest('tr').children[4].innerText;





function goBuy(){
const checkedCnt = document.querySelectorAll('.chk:checked').length;
let totalPrice = 0;
let itemCodes = '';
let buyCnts = '';
let cartCodes ='';



체크박스에 선택한 상품이 없을 때
if(checkedCnt ==0){
alert('선택한 상품이 없습니다.');
return;

(return 작성하여 if문 정지시킴)
}
 
체크된 상품의 totalPrice 총가격 가져 오겠다
const checkedBoxes = document.querySelectorAll('.chk:checked');
for(const checkBox of checkedBoxes){

const price = checkBox.closest('tr').children[5].innerText;



totalPrice는 숫자 0 들어갔으니 연산을 위해 price를 같은 인수로 바꾼다  
totalPrice = totalPrice + parseInt(price);



itemCode가져오기(input태그에서 value값으로 가져옴)

const itemCode = checkBox.value;
itemCodes = itemCodes + itemCode +',';

buyCnt 가져오기
const buyCnt = checkBox.closest('tr').children[4].innerText;
buyCnts = buyCnts + buyCnt + ',';

cartCode 가져오기 (data-cartcode)
const cartCode = checkBox.dataset.cartcode;
cartCodes = cartCodes + cartCode + ',';

}

총가격
document.querySelector('#totalPrice').value = totalPrice;
아이템코드
document.querySelector('#itemCode').value = itemCodes.substr(0, itemCodes.length -1);
구매수량
document.querySelector('#buyCnt').value = buyCnts.substr(0, buyCnts.length -1);

장바구니 상품 삭제 (value는 input태그에 넣을 값)
document.querySelector('#cartCode').value = cartCodes.substr(0, cartCodes.length -1);

버튼 누르면 form태그 실행
document.querySelector('form[action="insertBuys.buy"]').submit();

}

 

4. CONTROLLER

else if(command.equals("/insertBuys.buy")) {
       int totalPrice = Integer.parseInt(request.getParameter("totalPrice"));
       String itemCodes = request.getParameter("itemCode");
       String buyCnts = request.getParameter("buyCnt");
       String cartCodes = request.getParameter("cartCode");
       
       배열로 받아온 데이터 split 사용하여 , 제거 
       String[] itemCodeArr = itemCodes.split(",");
       String[] cartCodeArr = cartCodes.split(",");

       String[] buyCntArrString = buyCnts.split(",");

       (문자열로 받아오니까 정수로 바꿔줌)
       int[] buyCntArr = new int[buyCntArrString.length];
       
       for(int i=0 ; i< buyCntArr.length; i++) {
       buyCntArr[i]= Integer.parseInt(buyCntArrString[i]);

       }
       구매코드 출력
       String buyCode = buyService.selectBuyCode();
       

      구매자 ID 
       HttpSession session = request.getSession();
       MemberDTO loginInfo = (MemberDTO) session.getAttribute("loginInfo");
       String memId = loginInfo.getMemId();
      
       BuyDTO buy = new BuyDTO();
       buy.setTotalPrice(totalPrice);
       buy.setBuyCode(buyCode);
       buy.setMemId(memId);
       
      장바구니에서는 몇개를 구매할 지 모르기 때문에 List를 사용한다.
       List<BuyDetailDTO> buyDetailList = new ArrayList<>();
      
       또한, 데이터 몇개 들어올 지 모르기 때문에 for문으로 한 줄씩 넣어줌
       (itemCodeArr 또는 buyCntArr 중 하나로 for문을 만든다)
       for(int i =0 ; i < itemCodeArr.length; i++) {
       
       한 아이템 당 데이터 넣을 객체
       BuyDetailDTO buyDetailDTO = new BuyDetailDTO();
       buyDetailDTO.setItemCode(itemCodeArr[i]);
       buyDetailDTO.setBuyCnt(buyCntArr[i]);
       buyDetailDTO.setBuyCode(buyCode);
       buyDetailDTO.setBuyDetailCode(buyCode);
      

      위 내용을 List에 추가
       buyDetailList.add(buyDetailDTO)
       }
       

★cartCode 담는 방법은 2가지가 있다.
1. List를 만들어 foreach문으로 담기
1)cartCode 담을 통 만들기
List<String>cartCodeList = new ArrayList<>();
   

2) foreach문

for(String cartCode : cartCodeArr) {
cartCodeList.add(cartCode);
}



2. 배열을 List로 변환
List<String> cartCodeList = Arrays.asList(cartCodeArr);



   
장바구니에 담긴 상품목록 삭제
CartDTO cart = new CartDTO();
cart.setCartCodeList(cartCodeList);
       
구매이력 입력
buy.setBuyDetailList(buyDetailList);
       
insert 진행
buyService.cartBuy(buy, cart);