티스토리 뷰
Spring Boot + Angular : Shopping Site 만들기 v4 - 2 - 카트 상세 페이지 및 FormGroup 주문페이지 작성 - Rest Repository with JPA
Korean Eagle 2020. 6. 2. 22:020. 이 포스트는 카드 상세 페이지에서 수량을 조절하거나 담겨진 상품을 삭제하는 기능을 작성한다.
1. 우선 UI를 약간 변경하여 수량을 조절하는 버튼 2개와 삭제 버튼을 추가한다. 아래 소스의 중앙 부분에 있다.
1-1 버튼을 수량 좌우에 배치하고 클릭 이벤트가 발생하면 증감을 처리하는 메소드를 지정한다.
1-2 제거 버튼도 마찬가지로 클릭 시 이벤트를 처리하는 메소드를 지정한다.
1-3 각 이름이 incrementQuantity, decrementQuantity, removeItem이고 모두 현재 cartItem을 인자로 넘겨준다.
<div class="section-content section-content-p30">
<p class="alert alert-warning" *ngIf="cartItems.length === 0">
There is no item in your cart
</p>
<table class="table table-bordered">
<tr>
<th width="20%">Product Image</th>
<th width="50%">Product Detail</th>
<th width="30%"></th>
</tr>
<tr *ngFor="let item of cartItems">
<td><img src="{{ item.imageUrl }}" class="img-responsive" width="150px"></td>
<td>
<p></p>
<p><a routerLink="/products/{{ item.id }}">{{item.name}}</a></p>
<p>{{item.unitPrice}}</p>
</td>
<td>
<div class="items">
<label>Quantity: </label>
<span class="btn btn-secondary btn-sm" (click)="incrementQuantity(item)">
<i class="fas fa-plus"></i>
</span>
{{item.quantity}}
<span class="btn btn-secondary btn-sm" (click)="decrementQuantity(item)">
<i class="fas fa-minus"></i>
</span>
</div>
<p>Sub-total {{item.unitPrice * item.quantity | currency:'USD'}}</p>
<a class="primary-btn" (click)="removeItem(item)">Remove</a>
</td>
</tr>
<tr>
<td colspan="2"></td>
<td><b>Total Quantity: {{totalQuantity}}</b>
<p>Shipping FREE</p>
<b>Total Price: {{totalPrice | currency:'USD'}}</b><br>
<a href="checkout-page.html" class="primary-btn">Checkout</a>
</td>
</tr>
</table>
</div>
2. cart-details.component.html에서 정의한 메소드를 구현한다.
import { Component, OnInit } from '@angular/core';
import { CartService } from 'src/app/services/cart.service';
import { CartItem } from 'src/app/common/cart-item';
import { Product } from 'src/app/common/product';
@Component({
selector: 'app-cart-details',
templateUrl: './cart-details.component.html',
styleUrls: ['./cart-details.component.css']
})
export class CartDetailsComponent implements OnInit {
cartItems: CartItem[] = []
totalPrice: number = 0.00
totalQuantity: number = 0
constructor(private cartService: CartService) { }
ngOnInit(): void {
this.cartItems = this.cartService.cartItems
this.cartService.totalPrice.subscribe(data => this.totalPrice = data)
this.cartService.totalQuantity.subscribe(data => this.totalQuantity = data)
this.cartService.computeTotals()
}
incrementQuantity(item: CartItem) {
this.cartService.addToCart(item)
}
decrementQuantity(item: CartItem) {
this.cartService.decrementQuantity(item)
}
removeItem(item: CartItem) {
this.cartService.removeCartItem(item)
}
}
2-1 incrementQuantity, decrementQuantity는 1씩 줄이고 늘리는 기능이다.
2-1-1 incrementQuantity는 상품을 담는 addToCart 로직을 동일하게 사용하면 된다.
2-1-2 이렇게 하려면 CartService의 addToCart를 약간수정해서 Product 대신 CartItem을 받게 변경해야 한다.
2-1-3 addToCart의 인자를 변경하였기 때문에 아래의 소스처럼 이 메소드를 사용하는 부분도 수정해야 한다.
2-1-3-1 ProductList, ProductDetails에서 물건추가 할때 아래처럼 CartItem을 전달하는 것으로 수정해야 한다.
addToCart(product: Product) {
this.cartService.addToCart(new CartItem(product))
}
2-1-4 decrementQuantity는 주의해야 할 점이 있는데, 현재 수량이 1이면 삭제 후 카트에 존재하면 안된다.
2-1-4-1 따라서 1보다 클 경우는 단순히 quantity만 하나 줄이고 1이면 삭제를 하는 메소드를 사용하여 삭제한다.
2-1-4-2 전달되는 CartItem은 카트상세 페이지에 있는 cartItems: CartItem[]의 하나의 요소이고
2-1-4-2-1 이 요소는 CartService의 cartItems: CartItem[]를 참조하고 있다. 초기화 메소드에서 할당하고 있다.
2-1-4-2-2 즉 다 연결되어 있어서 하나 바꾸면 다 바뀐다. call by reference이다.
2-1-4-2-3 그래서 서비스의 decrementQuantity에서 item.quantity-- 만으로 충분하다.
2-1-5 삭제도 마찬가지인데 splice로 삭제를 하면 실제 연동되어 있는 배열이 바뀐다. 즉 다 그 상품이 삭제된다.
2-1-5-1 주의 할 점은 splice는 immutable을 구현하기 위해 새로운 배열을 생성하여 반환하기 때문에
2-1-5-2 반환된 값을 사용하면 CartDetails와 CartService의 카트물건정보가 각각의 객체를 관리하게 된다.
2-1-5-3 그래서 절대로 반환값을 사용해서는 안된다.
2-2 removeItem은 인자로 받은 CartItem을 삭제하는 기능이다.
2-2-1 아래를 보면 삭제기능을 CartService에서 별도의 메소드를 만들었다.
2-2-2 사용자가 상품을 삭제하는 버튼을 눌렀을 때 동작하거나 수량이 1인 상품의 수량을 줄인 경우 동작한다.
2-3 또 한 가지 주의 할 점은 computeTotals() 호출되는 시점이다.
2-3-1 값이 변경된 경우 반드시 Subject 전달을 의뢰하기 위해 computeTotals 실행해야 한다.
import { Injectable } from '@angular/core';
import { CartItem } from '../common/cart-item';
import { Subject } from 'rxjs';
import { Product } from '../common/product';
@Injectable({
providedIn: 'root'
})
export class CartService {
cartItems: CartItem[] = []
totalPrice: Subject<number> = new Subject()
totalQuantity: Subject<number> = new Subject()
constructor() { }
addToCart(cartItem: CartItem) {
let item: CartItem = undefined
let alreadyIn: boolean = false;
item = this.cartItems.find(item=> item.id === cartItem.id)
alreadyIn = item !== undefined;
if (alreadyIn) {
item.quantity++
} else {
this.cartItems.push(cartItem)
}
this.computeTotals();
}
computeTotals() {
this.totalPrice.next(
this.cartItems
.map(item => item.quantity * item.unitPrice)
.reduce((acc, eachTotal) => acc + eachTotal, 0)
);
this.totalQuantity.next(
this.cartItems
.map(item => item.quantity)
.reduce((acc, quantity) => acc + quantity, 0)
);
}
decrementQuantity(item: CartItem) {
if (item.quantity > 1) {
item.quantity--
this.computeTotals()
} else {
this.removeCartItem(item)
}
}
removeCartItem(item: CartItem) {
const index = this.cartItems.findIndex(product=> product.id === item.id)
if (index > -1) {
this.cartItems.splice(index, 1)
this.computeTotals()
}
}
}
3. 결과화면이다.
'Demos > Shopping mall' 카테고리의 다른 글
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- XML
- jsp
- 상속
- 자바
- Spring Security
- Spring
- form
- 로그인
- 매핑
- 하이버네이트
- 설정하기
- Many-To-Many
- Angular
- MYSQL
- 스프링부트
- Rest
- 설정
- Security
- one-to-many
- spring boot
- 외부파일
- login
- Validation
- 스프링
- one-to-one
- hibernate
- crud
- RestTemplate
- WebMvc
- mapping