셀렉트 박스
이번 게시글에서는 타임리프를 통해 셀렉트 박스를 처리하는 방법에 대해 알아보자.
예시 코드
도메인: DeliveryCode
/**
* FAST: 빠른 배송 * NORMAL: 일반 배송 * SLOW: 느린 배송
*/
@Data
@AllArgsConstructor
public class DeliveryCode {
private String code;
private String displayName;
}
도메인: Item
@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;
}
}
컨트롤러
@ModelAttribute
애너테이션이 어떻게 사용되었는지 보자.
@Slf4j
@Controller
@RequestMapping("/form/items")
@RequiredArgsConstructor
public class FormItemController {
private final ItemRepository itemRepository;
@ModelAttribute("deliveryCodes")
public List<DeliveryCode> deliveryCodes() {
List<DeliveryCode> deliveryCodes = new ArrayList<>();
deliveryCodes.add(new DeliveryCode("FAST", "빠른 배송"));
deliveryCodes.add(new DeliveryCode("NORMAL", "일반 배송"));
deliveryCodes.add(new DeliveryCode("SLOW", "느린 배송"));
return deliveryCodes;
}
// ------------- 상품 객체 추가를 위한 메서드 (위에서 살펴본 메서드들) -----------------
@GetMapping("/add")
public String addForm(Model model) {
model.addAttribute("item", new Item());
return "form/addForm";
}
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes) {
log.info("item.open={}", item.getOpen());
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/form/items/{itemId}";
}
}
@ModelAttribute
는 다른 메서드가 호출될 때마다, 본인 메서드를 실행하여 반환값을 model 객체에 바인딩한다. 따라서 List<DeliveryCode> deliveryCodes = new ArrayList<>();
를 통해, 다른 메서드가 호출될 때마다 ArrayList
객체가 생성된다. 그러므로, 다른 곳에서 미리 생성해둔 뒤 반환하는 구조로 설계해야 더 효율적이지만, 예시의 간소화를 위해 그대로 진행하겠다.
타임리프
<!DOCTYPE html>
<html xmlns:th="http:// www.thymeleaf.org">
<head>
<title>상품등록 폼</title>
</head>
<body>
<form action="item.html" th:action th:object="${item}" method="post">
<div>
<label for="itemName">상품명</label>
<input type="text" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요">
</div>
<div>
<label for="price">가격</label>
<input type="text" th:field="*{price}" class="form-control" placeholder="가격을 입력하세요">
</div>
<div>
<label for="quantity">수량</label>
<input type="text" th:field="*{quantity}" class="form-control" placeholder="수량을 입력하세요">
</div>
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" th:field="*{open}" class="form-check-input">
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
<div>
<div>등록 지역</div>
<div th:each="region : ${regions}" class="form-check form-check-inline">
<input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input">
<label th:for="${#ids.prev('regions')}"
th:text="${region.value}" class="form-check-label">서울</label>
</div>
</div>
<div>
<div>상품 종류</div>
<div th:each="type : ${itemTypes}" class="form-check form-check-inline">
<input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input">
<label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label">
BOOK
</label>
</div>
</div>
<!--------------------- 주목!!! ------------------------------->
<div>
<div>배송 방식</div>
<select th:field="*{deliveryCode}" class="form-select">
<option value="">==배송 방식 선택==</option>
<option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"
th:text="${deliveryCode.displayName}">FAST</option>
</select>
</div>
<!------------------------------------------------------------->
<button type="submit">상품 등록</button>
</form>
</body>
</html>
상세 설명
타임리프
<select th:field="*{deliveryCode}" ... >
th:field="*{deliveryCode}"
은 컨트롤러로부터 전달받은item
객체의deliveryCode
프로퍼티를 의미한다.id="itemType#"
(동적으로 생성된다.),name="itemType"
이 생성된다.
<option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}">
th:each="deliveryCode : ${deliveryCodes}"
을 통해, 컨트롤러로부터 전달받은deliveryCodes
객체를 하나씩 꺼내며 반복한다.
타임리프의 선택 확인
<option>
태그의 th:value="${deliveryCode.code}"
와, <select>
태그의 th:field="*{deliveryCode}"
의 값을 비교하여 selected
옵션을 자동적으로 추가해준다.
- 본 게시글은 김영한님의 강의를 토대로 정리한 글입니다.
- 더 자세한 내용을 알고 싶으신 분들이 계신다면, 해당 강의를 수강하시는 것을 추천드립니다.