● 판매 여부
● 판매 오픈 여부
● 체크 박스로 선택할 수 있다.
● 등록 지역
● 서울, 부산, 제주
● 체크 박스로 다중 선택할 수 있다.
● 상품 종류
● 도서, 식품, 기타
● 라디오 버튼으로 하나만 선택할 수 있다.
● 배송 방식
● 빠른 배송
● 일반 배송
● 느린 배송
● 셀렉트 박스로 하나만 선택할 수 있다.
ItemType - 상품 종류
package hello.itemservice.domain.item;
public enum ItemType {
BOOK("도서"), FOOD("식품"), ETC("기타");
private final String description;
ItemType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
상품 종류는 ENUM 을 사용한다. 설명을 위해 description 필드를 추가했다.
배송 방식 - DeliveryCode
package hello.itemservice.domain.item;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* FAST: 빠른 배송
* NORMAL: 일반 배송
* SLOW: 느린 배송
*/
@Data
@AllArgsConstructor
public class DeliveryCode {
private String code;
private String displayName;
}
배송 방식은 DeliveryCode 라는 클래스를 사용한다. code 는 FAST 같은 시스템에서 전달하는 값이고,
displayName 은 빠른 배송 같은 고객에게 보여주는 값이다.
Item - 상품
package hello.itemservice.domain.item;
import lombok.Data;
import java.util.List;
@Data
public class Item {
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
private Boolean open; //판매 여부
private List<String> regions; //등록 지역
private ItemType itemType; //상품 종류
private String deliveryCode; //배송 방식
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
단순 HTML 체크 박스
resources/templates/form/addForm.html 추가
<hr class="my-4">
<!-- single checkbox -->
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" name="open" class="form-check-input">
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
FormItemController 추가
@PostMapping("/add")
public String addItem(Item item, RedirectAttributes redirectAttributes) {
log.info("item.open={}", item.getOpen());
...
}
FormItemController 에 @Slf4j 애노테이션 추가
실행 로그
FormItemController : item.open=true //체크 박스를 선택하는 경우
FormItemController : item.open=null //체크 박스를 선택하지 않는 경우
체크 박스를 체크하면 HTML Form에서 open=on 이라는 값이 넘어간다. 스프링은 on 이라는 문자를
true 타입으로 변환해준다.
HTML에서 체크 박스를 선택하지 않고 폼을 전송하면 open 이라는 필드 자체가 서버로 전송되지 않는다
HTTP 요청 메시지 로깅
HTTP 요청 메시지를 서버에서 보고 싶으면 다음 설정을 추가하면 된다.
application.properties
logging.level.org.apache.coyote.http11=debug
HTTP 메시지 바디를 보면 open 의 이름도 전송이 되지 않는 것을 확인할 수 있다.
itemName=itemA&price=10000&quantity=10
HTML checkbox는 선택이 안되면 클라이언트에서 서버로 값 자체를 보내지 않는다. 수정의 경우에는
상황에 따라서 이 방식이 문제가 될 수 있다. 사용자가 의도적으로 체크되어 있던 값을 체크를 해제해도
저장시 아무 값도 넘어가지 않기 때문에, 서버 구현에 따라서 값이 오지 않은 것으로 판단해서 값을 변경하지
않을 수도 있다.
이런 문제를 해결하기 위해서 스프링 MVC는 약간의 트릭을 사용하는데, 히든 필드를 하나 만들어서,
_open 처럼 기존 체크 박스 이름 앞에 언더스코어( _ )를 붙여서 전송하면 체크를 해제했다고 인식할 수
있다. 히든 필드는 항상 전송된다. 따라서 체크를 해제한 경우 여기에서 open 은 전송되지 않고, _open 만
전송되는데, 이 경우 스프링 MVC는 체크를 해제했다고 판단한다.
체크 해제를 인식하기 위한 히든 필드
<input type="hidden" name="_open" value="on"/>
<!-- single checkbox -->
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" name="open" class="form-check-input">
<input type="hidden" name="_open" value="on"/> <!-- 히든 필드 추가 -->
<label for="open" class="form-check-label">판매 오픈</label></div>
</div>
실행 로그
FormItemController : item.open=true //체크 박스를 선택하는 경우
FormItemController : item.op
체크 박스 체크
open=on&_open=on
체크 박스를 체크하면 스프링 MVC가 open 에 값이 있는 것을 확인하고 사용한다. 이때 _open 은
무시한다.
체크 박스 미체크
_open=on
체크 박스를 체크하지 않으면 스프링 MVC가 _open 만 있는 것을 확인하고, open 의 값이 체크되지
않았다고 인식한다.
이 경우 서버에서 Boolean 타입을 찍어보면 결과가 null 이 아니라 false 인 것을 확인할 수 있다.
log.info("item.open={}", item.getOpen());
출처 : 김영한 MVC2 강의
'Spring > Thymeleaf' 카테고리의 다른 글
Thymeleaf - 체크 박스 - 멀티 (0) | 2022.09.07 |
---|---|
Thymeleaf - 체크 박스 - 단일2 (0) | 2022.09.07 |
Thymeleaf - 입력 폼 처리 (0) | 2022.09.07 |
Thymeleaf - 템플릿 레이아웃2 (0) | 2022.09.05 |
Thymeleaf - 템플릿 레이아웃1 (0) | 2022.09.04 |