이 글은 김영한 강사님의 강의를 참고하여 작성하였습니다.
이번 장은 굉장히 앞 장과 유사하기에 대표적인 기능들 위주로 정리.
th:object
th:object
에 설정해준 객체로 받아진다.*{...}
: 선택 변수 식이라고 한다. th:object
에서 선택한 객체에 접근한다.
th:field
th:object
에 설정해 준 객체의 내부와 매칭해준다.렌더링 전
<input type="text" th:field="*{itemName}" />
렌더링 후
<input type="text" id="itemName" name="itemName" th:value="*{itemName}" />
th:action
+)만약 th:action에 경로를 지정하지 않으면 현재 form에 지정한 action인 item.html을 호출하게 됩니다.
th:action 값이 있으면, 타임리프가 서버 렌더링 시, action 부분은 빈 값으로 변경된다.
-> 곧, 현재 있는 url과 같은 url로 html form을 method="post"로 post 방식으로 요청하는 식이다.
이 부분은 계속 헷갈리니 링크를 걸어두고 계속 보면 좋을 것 같다.
th:field
th:object
에 설정해 준 객체의 내부와 매칭해준다.<!-- 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>
- HTML checkbox는 선택이 안되면 클라이언트에서 서버로 값 자체를 보내지 않는다.
- 수정의 경우 [문제 발생]
- 사용자가 의도적으로 체크되어 있던 값을 체크를 해제해도 위의 상황으로 인해 저장시 아무 값도 넘어가지 않기 때문에
=>값이 오지 않은 것으로 판단해서 수정 상황에서 값을 변경하지 않을 수도 있다.- [해결 법] 👍😮
- 히든 필드
_open
처럼 기존 체크 박스 이름 앞에 언더스코어(_
)를 붙여서 전송하면 체크를 해제했다고 인식한다.
_open=on
=> 스프링 MVC는 체크를 해제했다고 판단open=on&_open=on
또한 서버에서 Boolean 타입을 찍어보면 결과가 null 이 아니라 false 인 것을 확인할 수 있다.
<hr class="my-4">
<!-- single checkbox -->
<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>
상품이 선택되지 않도록 막아놓는 것.
이전 저장된 상태가 true이면 그 결과를 가져와야 하는데 일일히 가져오기 귀찮다. 그렇기 때문에 타임리프의 th:field
를 사용하면, 값이 true 인 경우 체크를 자동으로 처리해준다
@ModelAttribute("regions")
public Map<String, String> regions() {
Map<String, String> regions = new LinkedHashMap<>();
regions.put("SEOUL", "서울");
regions.put("BUSAN", "부산");
regions.put("JEJU", "제주");
return regions;
}
등록 폼, 상세화면, 수정 폼에서 모두 서울, 부산, 제주라는 체크 박스를 반복해서 보여주어야 한다.
model.addAttribute(...)
을 사용해서 일일히 체크 박스를 구성하는 데이터를 반복해서 넣어주어야 한다.
- 해당 컨트롤러를 요청할 때 regions 에서 반환한 값이 자동으로 모델( model )에 담기게 된다.
-> 물론 이렇게 사용하지 않고, 각각의 컨트롤러 메서드에서 모델에 직접 데이터를 담아서 처리하는 방법도 있다.
- 멀티 체크박스
* 같은 이름의 '여러 체크박스'를 만들 수 있다.
-> but 생성할 때, 생성된 HTML 태그 속성에서 name 은 같아도 되지만, id 는 모두 달라야 한다.
=> 타임리프는 체크박스를each 루프
안에서 반복해서 만들 때 임의로 1 , 2 , 3 숫자를 뒤에 붙여준다.
<label for="id 값">
ids.prev(...)
, ids.next(...)
을 제공한다.<!-- multi checkbox -->
<div>
<div>등록 지역</div>
<div class="form-check form-check-inline">
<input type="checkbox" value="SEOUL" class="form-check-input"
id="regions1" name="regions">
<input type="hidden" name="_regions" value="on"/>
<label for="regions1"
class="form-check-label">서울</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" value="BUSAN" class="form-check-input"
id="regions2" name="regions">
<input type="hidden" name="_regions" value="on"/>
<label for="regions2"
class="form-check-label">부산</label>
</div>
<div class="form-check form-check-inline">
<input type="checkbox" value="JEJU" class="form-check-input"
id="regions3" name="regions">
<input type="hidden" name="_regions" value="on"/>
<label for="regions3"
class="form-check-label">제주</label>
</div>
</div>
- id 가 checkbox 에서 동적으로 생성된 regions1 , regions2 , regions3 에 맞추어 순서대로 입력된 것을 확인할 수 있다.
어디서 많이 본 문법일 것이다. 맞다 스프링 EL에서 봤을 것이다.
${T(hello.itemservice.domain.item.ItemType).values()}
- values()로 반환
->해당 ENUM의 모든 정보가 배열로 반환 [추천 x]
-> 왜? 추천하지 않냐? Enum의 파일 위치가 변경 됐을 때, 컴파일러가 '타임리프'까지 컴파일 에러를 잡아주지는 않아서
헷갈릴 수 있다. 그러나 th:object
가 위에 기입되어 있지 않은 상태에서 *{...}
이나, th:field
와 같이 되었을거라고 생각해서는 안된다.
꼭 확인하고 사용하자