20221017_mon
실습내용
- 장바구니목록페이지에서 수량변경 입력 후 변경버튼 클릭시, 디비반영과 수량도 update되지만, 옆 가격 영역과 하단의 총가격영역은 자동으로 변경되지 않는다.(페이지이동해야 변경된다.) 때문에 다시 Ajax를 사용해 자동변경되도록 만들어준다.
- 변경버튼 클릭시 모달창의 취소를 누르면 변경전 input태그에 있던 값으로 변경되어야한다.
: 방법은 여러가지이다. 함수를 사용하거나 이벤트를 거는 방법이 있다.
- 주의할점)
: 만약, input태그에 변경할 수량값을 입력 후 변경버튼을 클릭시, 모달창의 확인 버튼을 누르면 변경된 수량값이 뜨는데는 문제가 없지만, 다시 변경할 수량값을 input태그에 입력후 변경버튼을 클릭하여 모달창이 뜰 때, 취소버튼을 누르면 이전 변경된 값으로 나타나지는 것이 아니라, 가장 처음 저장되어있는 value값으로 나타나진다. -> 이 부분을 해결해야한다!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--해당 파일에 모든 쿼리문을 작성 -->
<mapper namespace="cartMapper">
<resultMap type="Kh.study.shop.cart.vo.CartVO" id="cart">
<id column="CART_CODE" property="cartCode"/>
<result column="ITEM_CODE" property="itemCode"/>
<result column="MEMBER_ID" property="memberId"/>
<result column="CART_AMOUNT" property="cartAmount"/>
<result column="REG_DATE" property="regDate"/>
<result column="TOTAL_PRICE" property="totalPrice"/>
<!-- 내가 만든 ver. 그냥 변수추가하기 -->
<result column="CATE_NAME" property="cateName"/>
<result column="ITEM_NAME" property="itemName"/>
<result column="ITEM_PRICE" property="itemPrice"/>
<result column="ATTACHED_NAME" property="attachedName"/>
<!-- 선생님 ver. 단, cartVO에 itemVO 추가하기 -->
<association property="itemVO" resultMap="itemMapper.item"></association>
</resultMap>
<resultMap type="Kh.study.shop.item.vo.CategoryVO" id="category">
<id column="CATE_CODE" property="cateCode"/>
<result column="CATE_NAME" property="cateName"/>
<result column="CATE_STATUS" property="cateStatus"/>
</resultMap>
<resultMap type="Kh.study.shop.item.vo.ItemVO" id="item">
<id column="ITEM_CODE" property="itemCode"/>
<result column="ITEM_NAME" property="itemName"/>
<result column="ITEM_PRICE" property="itemPrice"/>
<result column="ITEM_COMMENT" property="itemComment"/>
<result column="REG_DATE" property="regDate"/>
<result column="ITEM_STOCK" property="itemStock"/>
<result column="ITEM_STATUS" property="itemStatus"/>
<result column="CATE_CODE" property="cateCode"/>
<association property="categoryVO" resultMap="adminMapper.category" />
<collection property="imgList" resultMap="img"/>
</resultMap>
<resultMap type="Kh.study.shop.item.vo.ImgVO" id="img">
<id column="IMG_CODE" property="imgCode"/>
<result column="ORIGIN_NAME" property="originName"/>
<result column="ATTACHED_NAME" property="attachedName"/>
<result column="IS_MAIN" property="isMain"/>
<result column="ITEM_CODE" property="itemCode"/>
</resultMap>
<!-- 장바구니 목록조회 -->
<!-- 장바구니를 reg_date를 조회할 때 주의할 점: 반드시 장바구니에 등록한 날짜를 기준으로 해야한다. -->
<!-- 장바구니등록된 날짜 : C.REG_DATE -->
<select id="selectCartList" resultMap="cart">
SELECT CART_CODE
,IT.CATE_CODE
,CATE_NAME
,C.ITEM_CODE
,ITEM_NAME
,MEMBER_ID
,CART_AMOUNT
,TO_CHAR(C.REG_DATE,'YYYY-MM-DD') REG_DATE
,ITEM_PRICE
,TOTAL_PRICE
,ATTACHED_NAME
FROM SHOP_CART C,SHOP_ITEM IT,ITEM_IMG IM,ITEM_CATECGORY CT
WHERE C.ITEM_CODE = IT.ITEM_CODE
AND C.ITEM_CODE = IM.ITEM_CODE
and IT.CATE_CODE = CT.CATE_CODE
AND IS_MAIN = 'Y'
AND MEMBER_ID = #{memberId}
ORDER BY CART_CODE DESC
</select>
<!-- 장바구니 등록 (같은 상품이어도 별도로 등록됨)-->
<!-- totalPrice : 단가 * 수량 = 단가 * #{cartAmount} -->
<!-- 단가 : 서브쿼리로 구한다. -->
<!-- <insert id="regCart">
<selectKey resultType="String" keyProperty="cartCode" order="BEFORE">
SELECT 'CART_' ||LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE,6))),0)+1,3,0)
FROM SHOP_CART
</selectKey>
INSERT INTO SHOP_CART
( CART_CODE
,ITEM_CODE
,MEMBER_ID
,CART_AMOUNT
,TOTAL_PRICE
) VALUES (
#{cartCode},#{itemCode},#{memberId},#{cartAmount}
, (SELECT ITEM_PRICE FROM SHOP_ITEM WHERE ITEM_CODE = #{itemCode}) * #{cartAmount}
)
</insert> -->
<!-- 장바구니 등록쿼리 Merge 사용(같은상품끼리 자동 업데이트 묶어서 등록) -->
<insert id="regCart">
<selectKey resultType="String" keyProperty="cartCode" order="BEFORE">
SELECT 'CART_'|| LPAD(NVL(MAX(TO_NUMBER(SUBSTR(CART_CODE, 6))), 0) +1, 3, 0) FROM SHOP_CART
</selectKey>
MERGE INTO SHOP_CART
USING DUAL
ON(ITEM_CODE = #{itemCode} AND MEMBER_ID = #{memberId})
WHEN MATCHED THEN
UPDATE
SET
CART_AMOUNT = CART_AMOUNT + #{cartAmount}
, TOTAL_PRICE = (CART_AMOUNT + #{cartAmount}) *
(SELECT ITEM_PRICE FROM SHOP_ITEM WHERE ITEM_CODE = #{itemCode})
WHERE MEMBER_ID = #{memberId}
AND ITEM_CODE = #{itemCode}
WHEN NOT MATCHED THEN
INSERT( CART_CODE
, ITEM_CODE
, MEMBER_ID
, CART_AMOUNT
, TOTAL_PRICE
)VALUES(
#{cartCode}
, #{itemCode}
, #{memberId}
, #{cartAmount}
, (SELECT ITEM_PRICE FROM SHOP_ITEM
WHERE ITEM_CODE = #{itemCode}) * #{cartAmount}
)
</insert>
<!-- 재고 상품 수량 변경 -->
<!-- 수량이 바뀌면 총가격도 바뀌어야한다! 주의하기 -->
<!-- cat_code 값을 알면 item_Cdoe도 알수 있다! -> 이 점을 이용해서 이중서브쿼리문! -->
<update id="updateAmount">
UPDATE SHOP_CART
SET
CART_AMOUNT = #{cartAmount}
, TOTAL_PRICE = ( SELECT ITEM_PRICE
FROM SHOP_ITEM
WHERE ITEM_CODE =
(
SELECT ITEM_CODE
FROM SHOP_CART
WHERE CART_CODE = #{cartCode}
)
)
* #{cartAmount}
WHERE CART_CODE = #{cartCode}
</update>
<!-- 장바구니 선택삭제 -->
<!-- 체크된 cartCode만 삭제하면된다. -->
<!-- 하지만 실제 코드는 조건절에 or 로 모든 cartCode를 연달아 적어야한다! -->
<!-- 그래서 or을 반복적으로 사용하는 대신 in 연산자를 사용한다 -->
<!-- 통상적으로는 배열로 던져저 배열로 받아 사용한다. -->
<!-- 클릭시 데이터들고 페이지 이동하는 방법은? -->
<!-- form태그와 location차이는 url경로에 데이터가 보이냐 안보이냐 차이다. -->
<!-- 컨트롤러에서 cartVO 던지는데, 여기서 getter호출한다. -> cartVO.getCartCodeList()를 가져와서 for문돌린다 -->
<!-- 그러면 foreach문이 해석이 되면, 아래처럼 해석이된다.-->
<!-- DELETE SHOP_CART
WHERE CART_CODE IN
(CART_001, CART_002, CART_003,...,)-->
<delete id="deleteCarts">
DELETE SHOP_CART
WHERE CART_CODE IN
<foreach collection="cartCodeList" item="cartCode" separator="," open="(" close=")" >
#{cartCode}
</foreach>
</delete>
<!-- 선택 구매 -->
</mapper>
package Kh.study.shop.cart.service;
import java.util.ArrayList;
import java.util.List;
import Kh.study.shop.cart.vo.CartVO;
public interface CartService {
//장바구니 조회
List<CartVO> selectCartList(String memberId);
//장바구니 등록
void regCart(CartVO cartVO);
//상품수량 변경
void updateAmount(CartVO cartVO);
//선택삭제
void deleteCarts(CartVO cartVO);
}
package Kh.study.shop.cart.service;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import Kh.study.shop.cart.vo.CartVO;
@Service("cartService")
public class CartServiceImpl implements CartService {
@Autowired
private SqlSessionTemplate sqlSession;
@Override
public List<CartVO> selectCartList(String memberId) {
return sqlSession.selectList("cartMapper.selectCartList",memberId);
}
@Override
public void regCart(CartVO cartVO) {
sqlSession.insert("cartMapper.regCart",cartVO);
}
// 장바구니 상품 수량 변경
@Override
public void updateAmount(CartVO cartVO) {
sqlSession.insert("cartMapper.updateAmount",cartVO);
}
//선택삭제
@Override
public void deleteCarts(CartVO cartVO) {
sqlSession.delete("cartMapper.deleteCarts",cartVO);
}
}
package Kh.study.shop.cart.controller;
@Controller
@RequestMapping("/cart")
public class CartController {
@Resource(name = "cartService")
private CartService cartService;
@ResponseBody //ajax사용 하니까
@PostMapping("/regCart")
public void regCart(CartVO cartVO ,Authentication authentication) {
User user = (User)authentication.getPrincipal();
cartVO.setMemberId(user.getUsername());
cartService.regCart(cartVO);
// ajax 사용하면 model 필요없다.
// ajax 사용하니까 리턴 사용안함 -> return "content/cart/cart_list";
}
// ajax에서 if문으로 result값이 true일때 이동하는 페이지 경로
@GetMapping("/cartList")
public String cartList(Model model,Authentication authentication) {
// memberId 값 가져와서 cartList에 같이 던져주기
User user = (User)authentication.getPrincipal();
model.addAttribute("cartList",cartService.selectCartList(user.getUsername())) ;
// 전체 총 가격 데이터 (리스트에서 뽑아서 누적합으로 데이터 던져주기)
int finalPrice = 0;
for(CartVO e : cartService.selectCartList(user.getUsername())) {
finalPrice = finalPrice + e.getTotalPrice();
}
model.addAttribute("finalPrice",finalPrice);
return "content/cart/cart_list";
}
//선택삭제
@PostMapping("/deleteCart")
public String deleteCarts(String cartCodes) {//"cart_001,cart_002,cart_003"
String[] cartCodeArr = cartCodes.split(",");// 위처럼 넘어오는 cartCodes를 쉼표',' 로 분리한다. 그럼 문자열이 여러개나와서 배열로 받아야한다.
List<String> cartCodeList= Arrays.asList(cartCodeArr);
CartVO cartVO = new CartVO();//커맨드객체로 넘겨주려면 미리 cartVO에 cartCodes가 있으면 가능하다
cartVO.setCartCodeList(cartCodeList);
//cartCodeArr 안에 있는 cartCode를 하나하나 꺼내서 넣어준다.-> 반복문사용
//for(String cartCode : cartCodeArr) {
//cartCodeList.add(cartCode);
//}
cartService.deleteCarts(cartVO);
return "redirect:/cart/cartList";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout"
layout:decorate="~{layout/base_layout}"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<div layout:fragment="content">
<!-- 제목줄 -->
<div class="row mb-5">
<div class="col">
<h1>CART LIST</h1>
</div>
</div>
<!-- 장바구니 목록 테이블 -->
<div class="row ">
<div class="col ">
<table style="width: 100%;" class="table table-striped table-hover">
<colgroup>
<col width="*%" >
<col width="5%" >
<col width="15%" >
<col width="20%" >
<col width="25%" >
<col width="20%" >
<col width="20%" >
</colgroup>
<thead style="font-size: 20px; font-weight: bold; color: #425F57;">
<tr >
<td><input type="checkbox" id="allChk" checked="checked"></td>
<td>No.</td>
<td colspan="2" style="text-align: center;">상품 정보</td>
<td>수량</td>
<td>가격</td>
<td>등록 일자</td>
</tr>
</thead>
<tbody align="center" style="text-align: justify;">
<th:block th:if="${#lists.size(cartList) == 0}">
<div> 장바구니에 등록된 상품이 없습니다.</div>
</th:block>
<th:block th:unless="${#lists.size(cartList) == 0}">
<th:block th:each="cart : ${cartList}" >
<tr> <!-- 만약, td태그 밖에서 데이터 화면에 나타나게한다면? -> [[${cart.cateName}]] -->
<td><input th:value="${cart.cartCode}" type="checkbox" class="chk" checked="checked"></td>
<!-- 역순으로 순서 뽑는 방법 : 전체갯수 - index -->
<!-- 순서(No) 뽑는방법 : [[${cartStat.index}]] 이용 -->
<!-- 차례대로 순서 뽑는방법 : <th:block th:each="cart , status : ${cartList}" > <td th:text="${status.count}"> -->
<td>
<span th:text="${#lists.size(cartList) - cartStat.index}"></span>
</td>
<td ><img width="100px;" height="140px;" th:src="|@{/images/}${cart.attachedName}|"> </td>
<td >
[<span style="color: #749F82;" th:text=" ${cart.cateName}"></span>]
<span th:text=" ${cart.itemName}" ></span>
</td>
<td >
<input id="cartAmounts" type="number" min="0" th:value="${cart.cartAmount}" th:data-origin-amount="${cart.cartAmount}"><!-- value값은 화면에 보이는 값을 data-...보이지않는 값에 넣어준다. -->
<!-- 내가 클릭한 변경버튼의 해당하는 그 상품수량 숫자값을 들고오기위해 this 사용! -->
<button type="button" class="btn btn-light" th:onclick="goUpdateAmount(this);">변경</button>
</td>
<td><!-- (다른방법) [[${cart.itemVO.itemPrice}]]*[[${cart.cartAmount}]] -->
<div class="row">
<div class="col-6">
<div><span>[[${#numbers.formatCurrency(cart.itemPrice)}]]</span>*<span>[[${cart.cartAmount}]]</span> =</div><!-- 공백 표시 문자 기호 한칸띄어쓰기 -->
</div>
<div class="col-6">
<div class="totalPriceDiv" style="font-style: italic; font-weight: bold;"th:text="${#numbers.formatCurrency(cart.totalPrice)}" th:data-total-price="${cart.totalPrice}"> </div>
</div>
</div>
</td>
<td th:text="${cart.regDate}"> </td>
</tr>
</th:block>
</th:block>
</tbody>
</table>
</div>
</div>
<!-- 하단 영역 -->
<!-- 총가격 -->
<div class="row mt-5 mb-1" >
<div class="col-3"></div><!-- 줄맞춤용도 -->
<div class="col-3"></div><!-- 줄맞춤용도 -->
<div class="col-3"></div><!-- 줄맞춤용도 -->
<div class="col-3">
<div class="input-group mb-3 " >
<span class="input-group-text" id="inputGroup-sizing-default">
총가격
</span>
<div id="finalPriceTag" style="text-align: right;" th:data-total-price="${finalPrice}" th:text=" ${#numbers.formatCurrency(finalPrice)}" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default"></div>
</div>
</div>
</div>
<!-- 삭제 및 구매 버튼 -->
<div class="row mb-10" >
<div class="col" align="right">
<!-- 보이지않은 형태로 체크된 cartCode들을 form으로 보내줘야한다. -->
<form th:action="@{/cart/deleteCart}" method="post" id="deleteCartForm">
<input type="hidden" name="cartCodes" value="">
<!-- 바로 submit으로 보내지않고 함수를 실행해서 비어있는 value값을 데리고 와서 보내줘야한다 -->
<button th:onclick="goDelete();" type="button" class="btn btn-outline-danger">선택 삭제</button>
</form>
<button th:onclick="goBuy();" class="btn btn-outline-warning" style="color: #FF9F29;">선택 구매</button>
</div>
</div>
<!-- 수량변경 modal 창 -->
<div class="modal fade" id=updateAmountModal tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="row mb-3">
<div class="col">
<div>상품 수량 변경을 하시겠습니까?</div>
</div>
</div>
<div class="row">
<div class="col text-end">
<!-- th:onclick="|location.href='@{컨트롤러경로}'|" -->
<!-- js에서 데이터 보내려면, 태그를 잘 선택해서 받아서 사용하기위해 data- 속성이용해서 보내기. -->
<button id="updateAmountBtn" th:onclick="updateAmount();" data-cart-code="" data-cart-amount="" type="button" class="btn btn-sm" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;">
확인
</button>
<!-- 위 변경버튼 input에 있는 data-oring-amount값을 취소버튼 클릭시 세팅되도록 여기 data-oring-amount에 넣어줄거다 -->
<button data-origin-amount="" id="cancelBtn"type="button" th:onclick="rollbackAmount();" class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;">
<!-- <button id="rollbackAmountBtn" type="button" th:onclick="rollbackAmount();" data-cart-code="" data-cart-amount="" class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="--bs-btn-padding-y: .25rem; --bs-btn-padding-x: 3rem; --bs-btn-font-size: 1rem;"> -->
취소
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" th:src="@{/js/layout/cart_list.js}"></script>
</div>
</html>
// [변수 선언] ------------------------------------------------------------------------//
//제목 행의 체크박스의 체크여부를 확인
const allChk = document.querySelector('#allChk');
//제목줄 제외 모든 체크박스
const chks = document.querySelectorAll('.chk');
//모달창(수량변경)
const updateAmountModal = new bootstrap.Modal('#updateAmountModal');
////////////////////////////// 이벤트 정의 영역 ///////////////////////////////////////////
//[이벤트 1] 체크박스 전체 선택
allChk.addEventListener('click',function(){// allchk 값은 하나만 있기 때문 이벤트 가능!
const isChecked = allChk.checked;//체크된 제목줄 체크박스를 isChecked라고 한다.
const chk = document.querySelectorAll('.chk');// 테이블의 체크된 체크박스
//제목 줄의 체크박스가 체크 됐다면..
if(isChecked){//체크해ㅏㄹ
for(i = 0; i<chk.length; i++){
chk[i].checked = true;//체크된 클래스가 chk의 i번째 값은 true로 준다.
}
}
else{//체크해제해라
for(i = 0; i<chk.length; i++){
chk[i].checked = false;//체크된 클래스가 chk의 값은 true로 준다.
}
}
//전체 체크된 가격 총가격 나타내기
setFinalPrice();
});
// [이벤트 2] 체크박스 전체해제
// event for문 밖 변수선언
const chk = document.querySelectorAll('.chk');
for(const e of chk){
e.addEventListener('click',e=>{
const cnt = chk.length; //제목줄 밑의 전체 체크박스의 갯수는 cnt
const checkedCnt = document.querySelectorAll('.chk:checked').length; //클래스가 chk 인 것들 중에서 체크된것만 들고오겠다.그것의 갯수.
if(cnt == checkedCnt){// 체크해라
document.querySelector('#allChk').checked = true;
}
else{//체크하지마라
document.querySelector('#allChk').checked = false;
}
//전체 체크된 가격 총가격 나타내기
//setFinalPrice();
});
}
// [이벤트 3 ]장바구니 목록에 있는 체크박스 클릭 시 진행
// !!! 값이 여러개에 이벤트 불가능! -> for문돌려서 하나씩 빼서 여러번 실시한다.
for(const chk of chks){
chk.addEventListener('click',function(){//체크박스 클릭시 실행
setFinalPrice();//체크된 가격 하나씩 빼서 총가격 누적합계산하겠다.
});
}
///////////////////////////////////// [함수 정의] ///////////////////////////////////////////////////////////////////////////
//[함수 3] 총가격을 세팅하는 함수
function setFinalPrice(){
//체크된 박스 태그 선택
const checkedBoxes = document.querySelectorAll('.chk:checked');
//체크된 체크박스의 totalPrice 값 선택
let finalPrice = 0;
for(const checkBox of checkedBoxes){ // parseInt : 자바스크립트_숫자를 문자로 변환
const totalPrice = parseInt(checkBox.closest('tr').querySelector('.totalPriceDiv').dataset.totalPrice);
// 만약 data-totalprice로 데이터를 가져온다면?(th: 타임리프 사용해야 변수값 들고온다)
finalPrice = finalPrice + totalPrice;
}
//선택된 전체 값 더하기
// 천단위 구분 기호 : .toLocaleString()
document.querySelector('#finalPriceTag').innerText = '₩'+ finalPrice.toLocaleString() ;
}
// [함수 4 ] 수량변경 버튼 클릭시 진행되는 함수
function goUpdateAmount(selectedTag){// selectedTag :this로 넘어오는 태그(수량값의 변경버튼 클릭한 태그 의미)
updateAmountModal.show();//맨위에 선언한 변수 모달을 가져와 열어주도록 한다.
// 수량값과 카트코드값을 들고와야하기때문에 태그 선택해서 가져오기! 어떻게?
// 클릭한 버튼의 data-cart-code, data-cart-amount 속성의 값을 수량을 변경하고자하는 데이터로 세팅
// 내가 지금 클릭한 태그의 바로 옆에있는 input태그의 수량값 들고오자. -> this 사용하기
// this 를 사용하면?
// selectedTag를 기준으로 원하는 태그를 찾아갈 수 있어 용이하다!
// - 수량 (cartAmount)
// --1) input태그 number값으로 수량 태그 선택시 :
const cartAmount = selectedTag.closest('tr').querySelector('input[type="number"]').value;
// --2) id값으로 수량 태그 선택시 : const cartAmountB = selectedTag.querySelector('#cartAmounts').value;
// - 카트코드 (cartCode): 체크박스에다가 카트코드 부여하기 value값으로
const cartCode = selectedTag.closest('tr').querySelector('input[type="checkbox"]').value;
// - 변경된 수량 태그선택
//const itemPrice = document.querySelector('#itemPriceTag').value;
//alert(itemPrice);
// data- 속성값에 위에서 선택한 태그값들을 바로 넣어준다.
document.querySelector('#updateAmountBtn').dataset.cartCode = cartCode;//cart-code
document.querySelector('#updateAmountBtn').dataset.cartAmount = cartAmount;//cart-amount
//document.querySelector('#updateAmountBtn').dataset.itemPrice = cartAmount;
//기존 장바구니 수량(originAmount)을 취소버튼에 전달한다.
const originAmount = selectedTag.closest('tr').querySelector('input[type="number"]').dataset.originAmount;//origin-amount
document.querySelector('#cancelBtn').dataset.originAmount = originAmount;
}
// [함수 5] 수량버튼 클릭 후, 나타나는 모달창의 확인버튼 클릭시, 진행되는 함수
function updateAmount(){// 여기 괄호안 매개변수는 html연결된 데이터!
const cartCode = document.querySelector('#updateAmountBtn').dataset.cartCode;
const cartAmount = document.querySelector('#updateAmountBtn').dataset.cartAmount;
//const itemPrice = document.querySelector('#updateAmountBtn').dataset.itemPrice;
$.ajax({
url: '/cart/updateAmount', //요청경로
type: 'post',
// 여기 데이터는 controller에서 던져받는 데이터!
data: {'cartCode':cartCode
,'cartAmount':cartAmount}, //필요한 데이터
success: function(result) {
alert('성공');
//주의!! 모달창은 알아서 닫히지않는다. 페이지이동을 하지않은 이상! 때문에 코드를 직접 써서 닫아줘야한다.
updateAmountModal.hide();
//모달창이 닫히자마자 input태그 입력한 상품수량값으로 테이블 옆줄의 수량영역도 바뀌어야 한다.
//장바구니 상품에 대한 수량 및 가격 갱신
// : 이 또한 제목줄 제외 모든 체크박스를 하나씩 빼서 비교
// : 실제로 수정되어 저장된 카트코드(cartAmount)와 일치하면 바꾼다.
for(const chk of chks){
if(chk.value == cartCode){
chk.closest('tr').querySelector('input[type="number"]').dataset.originAmount = cartAmount;
}
}
},
error: function() {
alert('실패');
}
});
}
// 수량변경 모달(팝업)창에서 취소 버튼 클릭 시 진행되는 함수
function rollbackAmount(){
// 이미 수량 변경버튼을 클릭하면, 변경할 상품의 cartCode값을 가지고는 있다.
// 그런데 이는 모달창에 뜨는 '확인'버튼에 갖고있다.
// 그래서 이를 반복문으로 비교하여 일치하면 그 줄에 있는 수량을 롤백시켜야하는 원래 값으로 돌려준다.
// 제묵줄 제외한 모든 체크박스에 반복문 접근하여 cartCode 가져온다.
//수량을 롤백시켜야하는 cartCode와 비교
const selectedCartCode = document.querySelector('#updateAmountBtn').dataset.cartCode;
const originAmount = document.querySelector('#cancelBtn').dataset.originAmount;
for(const chk of chks){//이 chk의 밸류값이 체크박스의 cartCode와 같다. -> th:value="${cart.cartCode}"
// 반복문을 돌리면서 비교하는데, 내가 변경하고픈 체크박스의 input태그의 cart코드와 일치하다면
if(chk.value == selectedCartCode){
//수량을 원래대로 돌려야하는 input태그를 찾아가서 원래 수량값으로 돌려줘야한다.
chk.closest('tr').querySelector('input[type="number"]').value = originAmount;
//하지만, 문제점발생
// 실제로 수량변경 후 다시 취소버튼을 클릭하면 변경한값으로 나타나는 것이아니라 무조건 첫번째 저장된 originAmount값만 뜬다.
}
}
//실제로 수량변경이 완료되면
}
// [함수 2 ] 선택삭제 클릭 시
function goDelete(){
const deleteForm = document.querySelector('#deleteCartForm');
//체크한 cartCode 다 들고 온다.(cartCode값은 체크박스안에 value값과 같다)
const checkedChks = document.querySelectorAll('.chk:checked');
//--선택한 상품이 없을 때
const checkedCnt = document.querySelectorAll('.chk:checked').length;
if(checkedCnt == 0){
alert('선택한 상품이 없습니다.');
return ;
}
//--선택된 체크박스들 있을 때
//데이터를 주고받을 땐, 문자열로 만드는게 가장 편하다.
let cartCodes = '';//우선,빈문자로 만든다.
for(const checkedChk of checkedChks){
cartCodes = cartCodes + checkedChk.value + ',';// "CART_001,CART_002,CART_003"
}
deleteForm.querySelector('input').value = cartCodes; //빈 value값에 위에서 만든 문자열 cartCodes값을 채워준다.
//cartCodes =cartCodes.substr(0,cartCodes.length-1);//가져가서 사용할땐 문자열을 잘라줘야한다.
deleteForm.submit();// (데이터넘기며 페이지이동 방법 2) form태그 사용시 :선택 삭제 form태그에 바로 submit주지않고 button으로 준다음 이렇게 value값 가져온 후 여기서 submit주면된다.
}
//내가 가져온 소스
//---------------------------------------------------------------------------------------//
// [함수 1] 선택구매버튼을 클릭시
function goBuy(){
const checkedCnt = document.querySelectorAll('.chk:Checked').length;//체크박스들중에서 체크된 것들만!(all)그것의 갯수.
if(checkedCnt == 0){
alert('선택한 상품이 없습니다.');
return ;
}
const checkedBoxes = document.querySelectorAll('.chk:checked'); // 여러개가지고 오니까 all 사용
let totalPrice = 0; // 변하기때문 let 사용한다.
let itemCodes = ''; // 변하기때문 let 사용한다.
let cartAmounts = ''; // 변하기때문 let 사용한다.
let cartCodes = ''; // 변하기때문 let 사용한다.
for(const checkBox of checkedBoxes){//체크된 checkedBoxes들 중에 하나씩 뺀다 그것을 checkBox 라고한다.
totalPrice = totalPrice + parseInt(price);
//상품코드 값 선택 후 누적합 계산
const itemCode = checkBox.value;
itemCodes = itemCodes + itemCode +',';//ITEM_001,ITEM_002,
//구매수량 값 선택 후 누적합 계산
const cartAmount = checkBox.closest('tr').children[4].innerText;
cartAmounts = cartAmounts + cartAmount +',';
//카테고리코드 값 선택 후 누적 합 계산
const cartCode= checkBox.dataset.cartcode;//jsp에서 cartCode이지만 js는 항상 소문자로 가져오기때문에 소문자로 작성해야 오류발생x
console.log(checkBox.dataset);// 개발자콘솔창확인시, data-cart-code/data-cartCode(data-cartcode) 의 차이점 파악하기위해
cartCodes = cartCodes + cartCode +',';//CART_001.CART_002,..
}
document.querySelector('form[action="insertBuys.buy"]').submit();
}
//
다음 실습내용
- buy_info.html
- 주문 정보(No. 상품명 상품대표이미지 가격(단가) 수량) -> 목록으로 띄운다.
: 가장마지막은 총 구매액 띄운다.
- 주문자 정보() : id, 이름 , 연락처, 주소
: 화면 가장 아래 주문확인 버튼 만들기
: 버튼 클릭 시, db에 insert 완료시키기