타임리프(Thymeleaf)2_ 스프링 통합 & 폼

이동건 (불꽃냥펀치)·2024년 12월 6일
0

타임리프_스프링 통합

입력 폼 처리

th:object: 커멘드 객체를 지정한다
*{...}: 선택변수식아라 하며 th:object 에서 선택한 객체에 접근한다.
th:field: HTML 태그의 id , name , value 속성을 자동으로 처리해준다.

등록폼 처리


 @GetMapping("/add")
 public String addForm(Model model) {
     model.addAttribute("item", new Item());
     return "form/addForm";
}
 <form action="item.html" th:action th:object="${item}" method="post">
     <div>
<label for="itemName">상품명</label>
<input type="text" id="itemName" th:field="*{itemName}" 
class="form- control" placeholder="이름을 입력하세요">
</div> 
<div>
	<label for="price">가격</label>
	<input type="text" id="price" th:field="*{price}" 
    class="form-control" placeholder="가격을 입력하세요">
</div> 
<div>
	<label for="quantity">수량</label>
	<input type="text" id="quantity" th:field="*{quantity}" 
    class="form- control" placeholder="수량을 입력하세요">
</div>

th:object="${item}" : <form> 에서 사용할 객체를 지정한다. 선택 변수 식( *{...} )을 적용할 수 있다.

th:field="*{itemName}"

  • th:field="*{itemName}"id,name,value 속성을 모두 자동으로 만들어준다.
    • id:th:field에서 지정한 변수 이름과 같다.
    • name: th:field에서 지정한 변수 이름과 같다.
    • value: th:field에서 지정한 변수의 값을 사용한다.



체크박스, 라디오 버튼, 셀렉트 박스

체크박스

<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>

폼에 해당 HTML 태그를 추가 해 이 데이터가 전달되는 상황이다.

 @PostMapping("/add")
 public String addItem(Item item, RedirectAttributes redirectAttributes) {
     log.info("item.open={}", item.getOpen());
     ...
 }

컨트롤러로 해당 폼을 전달받은 후 log를 찍어보면 체크박스를 선택하면 true , 선택하지 않으면 null값이 전달된다.

<input type="hidden" name="_open" value="on"/>

체크 박스 이름 앞에 언더스코어를 붙여서 전송하면 체크를 해제했다고 인식할 수 있다.

체크를 해제한 경우 여기에서 open은 전송되지 않고, _open만 전송되는데 이 경우 스프링 mvc는 체크를 해제했다고 판단한다.

하지만 개발할 때 마다 이렇게 히든 필드를 추가하는 것은 매우 귀찮다. 타임리프가 제공하는 폼 기능을 사용하면 이런 부분을 자동으로 처리할 수 있다.

<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>

th:field="*{open}"을 사용하면 _open코드를 사용하지않고 객체에 저장된 값을 자동으로 꺼내 체크박스에 반영한다.

주의해야 할 점은 폼에서 th:object="${item}"을 설정하지 않았다면 th:field="*{open}"을 사용하면 오류가 발생한다. 이 경우 th:field="${item.open}"으로 설정해야한다.



체크 박스_멀티

@ModelAttribute("regions")
public Map<String, String> regions() {
	Map<String, String> regions = new LinkedHashMap<>(); 	
    regions.put("SEOUL", "서울");
	regions.put("BUSAN", "부산");
	regions.put("JEJU", "제주");
	return regions;
}

@ModelAttribute 특별한 사용법

@ModelAttribute는 컨트롤러에 있는 별도의 메서드에 적용할 수 있다.
이렇게하면 해당 컨트롤러를 요청할 때 regions에 반환한 값이 자동으로 모델(model)에 담기게된다.

<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>

th:for="${#ids.prev('regions')}"

멀티 체크박스는 같은 이름의 여러 체크박스를 만들 수 있는데, 이런식으로 여러개를 만들면 고유한 값을 가져야 할 id값이 같아진다. id값을 다르게 하기위해 타임리프는 체크박스를 each 루프 안에서 반복해서 만들 때 임의로 숫자를 붙인다.


라디오 버튼

@ModelAttribute("itemTypes")
 public ItemType[] itemTypes() {
     return ItemType.values();
 }

Enum타입으로 만든 객체를 values 메서드를 이용해 배열로 만들었다.

<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>

이 역시 HTML로 전달된 Enum 객체의 메서드를 활용해서 각 정보를 사용자에게 보여주고 있다.
이때 라디오 박스에 아무값도 선택하지 않으면 null 값으로 전달된다.

<div>
<div>상품 종류</div>
<div th:each="type : ${itemTypes}" class="form-check form-check-inline">
         <input type="radio" th:field="${item.itemType}" th:value="$
 {type.name()}" class="form-check-input" disabled>
         <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
 class="form-check-label">
           BOOK
         </label>
     </div>
 </div>

여기에서는 th:field="${item.itemType}"으로도 사용이 가능하다는 것을 보여주기 위해 이 방식을 사용했다.

th:object=${item}이 설정되어있지 않으면 th:field="*{itemType}"은 사용할 수 없다.



셀렉트 박스

셀렉트 박스는 여러 선택지 중에 하나를 선택할 때 사용할 수 있다.

@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;
}
<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>








출처: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard

profile
자바를 사랑합니다

0개의 댓글

관련 채용 정보