본문 바로가기

springboot

[springboot - thymeleaf] 쇼핑몰 장바구니 페이지 구현

 

 

장바구니 페이지에서 필요한 기능은 상품 선택, 수량 변경, 취소, 총 금액 표시이다.

 

처음에는 form 태그로 table 전체를 감싸고, 수량 변경, 취소 등은 th:formaction으로 바인딩했다.

선택 상품 주문도, post 요청의 body data로 보낼 생각이었다.

 

하지만 checkbox의 데이터를 실시간으로 바꿀 수 있는 것을 기억해내고(...)

체크 박스 부분, 수량 변경 부분을 각각 form으로 감싸서 해결했다. 

 

shoppingBag.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header" />
<body>
<div class="container">
    <div th:replace="fragments/bodyHeader :: bodyHeader"/>
    <div>
        <h3>장바구니</h3>

        <div th:if="${orderForm.list.size()==0}" class="jumbotron">
            <h3>장바구니에 추가한 상품이 없습니다.</h3>
        </div>
        <table class="table table-striped" th:if="${orderForm.list.size()>0}">
                <thead>
                <tr>
                    <th></th> <th>#</th> <th>상품명</th> <th>가격</th> <th>수량</th> <th>합계</th> <th></th>
                </tr>
                </thead>
                <tbody>
                <tr th:each="item, stat : ${orderForm.list}">
                    <td>
                        <form th:action="@{/shop/check(id=${item.id})}" method="post">
                            <input type="checkbox" th:checked="${item.checked}" onclick="submit();"/>
                        </form>
                    </td>
                    <td th:text="${item.itemId}"></td>
                    <td><a th:text="${item.name}" th:href="@{/items/detail(itemId=${item.itemId})}"></a></td>
                    <td th:text="${item.price}"></td>
                    <td>
                        <form th:action="@{/shop/update}" method="post">
                            <input type="hidden" th:value="${item.id}" name="id">
                            <input onclick="submit();" name="count" type="number" class="form-control" th:min="1" th:max="${item.stockQuantity}>10? 10:${item.stockQuantity}" th:value="${item.count}"/>
                        </form>

                    </td>
                    <td th:text="${item.totalPrice}"></td>
                    <td>
                        <a href="#" th:href="'javascript:cancel('+${item.id}+')'">취소</a>
                    </td>
                </tr>
                </tbody>
            </table>
            <br/>
            <h3 style="float: right">총 금액 : <a th:text="${totalPrice}"></a> 원</h3>
            <form method="post" action="@{order/all}">
                <button style="width: 100%; margin-bottom: 5px" class="btn btn-primary" type="submit" th:formaction="@{order/select}">선택 상품 주문</button>
                <button style="width: 100%" class="btn btn-primary" type="submit" >전체 상품 주문</button>
            </form>
    </div>
    <div th:replace="fragments/footer :: footer"/>
</div> <!-- /container -->
</body>
<script th:inline="javascript">
    function cancel(id) {
        var form = document.createElement("form");
        form.setAttribute("method", "post");
        form.setAttribute("action", "/shop/" + id + "/delete");
        document.body.appendChild(form);
        form.submit();
    }
</script>
</html>

 

ShoppingBagController.java

...
    @PostMapping(value = {"/update"})
    public String update(@AuthenticationPrincipal LoginUserDetails member,
                         @RequestParam("id") Long id,
                         @RequestParam("count") int count) {

        memberService.updateBaggedItemCount(id, count);

        return "redirect:/shop";
    }
    
    @PostMapping(value = "/check")
    public String check(@AuthenticationPrincipal LoginUserDetails member,
                        @RequestParam("id") Long id) {

        memberService.updateBaggedItemCheck(id);

        return "redirect:/shop";
    }
    ...

 

선택 상품 주문같은 경우는 DB의 BAGGED_ITEM에 checked 칼럼을 두어서 그걸 보고 가져올 수 있도록 했다. 

 

 


더보기

총 금액은 html에서 계산하고 check된 데이터만 넘겨서

결제하고자 하는 상품만 장바구니에서 빼고 결제하는 게 더 나을 것 같다

그럼 굳이 서버와의 통신을 매번 하지 않아도 되고

서버는 총 결제 상품에 대해서만 체크하면 되니 더 괜찮은 방법인 것 같다 - 2022.11.4