[Thymeleaf] 타임리프 스프링 통합1
통합으로 추가되는 기능
- 스프링의 SpringEL 문법 통합
${@myBean.doSomething()}
처럼 스프링 빈 호출 지원- 편리한 폼 관리를 위한 추가 속성
th:object
(기능 강화, 폼 커맨드 객체 선택)th:field
,th:errors
,th:errorclass
- 폼 컴포넌트 기능
- checkbox, radio button, List 등을 편리하게 사용할 수 있는 기능 지원
- 스프링 메시지, 국제화 기능의 편리한 통합
- 스프링의 검증, 오류 처리 통합
- 스프링의 변환 서비스 통합(ConversionService)
입력 폼 처리
th:object
: 커맨드 객체를 지정한다.*{...}
: 선택 변수 식.th:object
에서 선택한 객체에 접근한다.th:field
- HTML 태그의
id
,name
,value
속성을 자동으로 처리해준다.
- HTML 태그의
렌더링 전
<input type="text" th:field="*{itemName}"/>
렌더링 후
<input type="text" id="itemName" name="itemName" th:value="*{itemName}"/>
등록 폼
th:object
를 적용하려면 해당 오브젝트 정보를 먼저 넘겨주어야 한다.
Controller
@GetMapping("/add")
public String addForm(Model model) {
model.addAttribute("item", new Item());
return "form/addForm";
}
등록 폼이기 때문에 빈 오브젝트를 만들어서 뷰에 전달했다.
addForm.html
<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}"
${item.itemName}
과 같다.
th:field
는id
,name
,value
속성으르 자동으로 만들어준다.value=""
- 따라서,
id
속성을 제거해도 자동으로 만들어준다.
요구사항 추가
ItemType.enum
상품 종류(ENUM)
public enum ItemType {
BOOK("도서"), FOOD("식품"), ETC("기타");
private final String description;
ItemType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
DeliveryCode.class
배송 방식
/**
* FAST: 빠른 배송
* NORMAL: 일반 배송
* SLOW: 느린 배송
*/
@Data
@AllArgsConstructor
public class DeliveryCode {
private String code;
private String displayName;
}
@AllArgsConstructor
: 모든 필드 값을 파라미터로 받는 생성자를 만듦code
는FAST
같은 시스템에서 전달하는 값,displayName
은빠른 배송
같은 고객에게 보여주는 값.
Item.class
상품
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; //배송 방식
체크 박스 - 단일1
addForm.html
<div class="form-check">
<input type="checkbox" id="open" name="open" class="form-check-input">
<label for="open" class="form-check-label">판매 오픈</label>
</div>
- 체크 박스를 체크하면 HTML Form에서
open=on
이라는 값이 넘어간다. - 스프링은
on
문자를true
타입으로 변환해준다.
[주의]
HTML에서 체크 박스를 선택하지 않고 폼을 전송하면open
이라는 필드 자체가 서버로 전송되지 않는다.(null)
이런 문제를 해결하기 위해 스프링 MVC는 히든 필드(_open
)를 만들어서 전송하게 되면 체크를 해제했다고 인식할 수 있다.
히든 필드는 항상 전송되기 때문에 체크를 해제한 경우 open
은 전송되지 않고, _open
만 전송되어 스프링 MVC는 체크를 해제했다고 판단한다.
체크 해제를 인식하기 위한 히든 필드
<input type="hidden" name="_open" value="on"/>
(해제시 false값이 넘어간다.)
체크 박스 체크
open=on&_open=on
체크시 스프링 MVC가 open
에 값이 있는 것을 확인하고 사용.(_open
은 무시.)
미체크
_open=on
스프링 MVC가 _open
만 있는 것을 확인하여 체크되지 않았다고 인식한다.
서버에서 boolean
타입을 찍어보면 null
이 아닌 false
가 나오게된다.
체크 박스 - 단일2
addForm.html
<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>
타임리프를 사용하면 체크 박스의 히든 필드 부분도 해결해준다. HTML 결과를 보면 히든 필드 부분이 자동으로 생성되어 있다.
item.html
<div class="form-check">
<input type="checkbox" id="open" th:field="${item.open}"
class="form-check-input" disabled>
<label for="open" class="form-check-label">판매 오픈</label>
</div>
item.html
에는 th:object
를 사용하지 않아 th:field="${item.open}"
으로 적었다.
생성 결과
<div class="form-check">
<input type="checkbox" id="open" class="form-check-input" disabled
name="open" value="true" checked="checked">
<label for="open" class="form-check-label">판매 오픈</label>
</div>
checked="checked"
타임리프의 th:field
를 사용하면 값이 true
인 경우 checked
속성이 자동으로 추가된다.
<출처 : 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술(김영한)>
댓글남기기