인프런 김영한님의 Spring강의에서 공부한것을 올리며, Thymeleaf의 경우 unit 단위로 공부후 각각 정리하는 글을 작성하겠습니다.
체크 박스
이번시간에는 체크박스의 문제점에 대하여 알아본 후, 이걸 Spring MVC 의 기능을 통해 수정해보고, 마지막으로 타임리프로 수정해볼것 이다.
우선 다음과 같은 컨트롤러와 체크박스가 있다고 해보자.
@GetMapping("/add")
public String addForm(Model model) {
model.addAttribute("item", new Item());
return "form/addForm";
}
그냥 등록 Form을 보여주기 위한 컨트롤러 입니다.
● 단순 HTML 체크 박스
<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 : item.open=true //체크 박스를 선택하는 경우
- FormItemController : item.open=null //체크 박스를 선택하지 않는 경우
체크 박스를 체크하면 HTML Form에서 open=on 이라는 값이 넘어간다. 스프링은 on 이라는 문자를 true 타입으로 변환해준다.
문제는 체크박스를 선택하지 않을때 발생한다.
HTML에서 체크 박스를 선택하지 않고 폼을 전송하면 open 이라는 필드 자체가 서버로 전송되지 않는다.
체크를 했으면 true, 안했으면 false 로 명확하게 넘어와야 서버 입장에서 깔끔한 처리가 되는데...
체크를 했으면 true, 안했을때는 아무정보가 넘어오지 않아 서버 입장에서는 true인지 false인지 판단하기가 애매하다.
체크를 하지 않고 넘오온 데이터를 서버에서 Boolean 타입으로 찍어보면 결과가 null로 나온다.
이런 문제를 해결하기 위해서 스프링 MVC는 약간의 트릭을 사용한다!
히든 필드를 하나 만들어서, _open처럼 기존 체크 박스 이름 앞에 언더스코어(_)를 붙여서 전송하면 체크를 해제했다고 인식할 수 있다.
히든 필드는 항상 전송된다. 따라서 체크를 해제한 경우 여기에서 open 은 전송되지 않고, _open 만 전송되는데, 이 경우 스프링 MVC는 체크를 해제했다고 판단한다.
위 HTML 코드에서 히든 필드 부분을 추가해 봅시다!
<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.open=false //체크 박스를 선택하지 않는 경우
● 체크 박스 체크 : open=on&_open=on
체크 박스를 체크하면 스프링 MVC가 open 에 값이 있는 것을 확인하고 사용한다. 이때 _open 은 무시한다.
● 체크 박스 미체크 : _open=on
체크 박스를 체크하지 않으면 스프링 MVC가 _open 만 있는 것을 확인하고, open 의 값이 체크되지 않았다고 인식한다.
이 경우 서버에서 Boolean 타입을 찍어보면 결과가 null 이 아니라 false 인 것을 확인할 수 있다.
하지만 아직도 이걸 하나하나 히든 필드를 추가할 생각하면 너무 힘들다.. 이를 타임리프가 도와준다.
Thymeleaf 를 통한 개선
● 상품 등록 Form
타임리프에서 제공하는 체크 박스코드로 변경하면 다음과 같다.
<div>판매 여부</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" name="open" th:field="${item.open}" class="form-check-input">
<label for="open" class="form-check-label">판매 오픈</label>
</div>
</div>
타임리프에서의 th:field를 추가해 주었다. field 사용하면 체크박스의 히든필드 부분까지 해결해 준다.
다음은 위와같이 코드를 수정한후 확인한 소스코드이다.
사진 설명을 입력하세요.
우리가 HTML 상에서는 th:field 부분만 추가했다.
하지만 실제 소스코드를 열어보면 우리가 추가하지는 않았지만 타임리프가 자동으로 히든필드를 생성하여 추가해 주었다.
타임리프의 체크 확인 ( checked="checked" )
체크 박스에서 판매 여부를 선택해서 저장하면, 조회시에 checked 속성이 추가된 것을 확인할 수 있다.
이런 부분을 개발자가 직접 처리하려면 상당히 번거롭다. 타임리프의 th:field 를 사용하면, 값이 true 인 경우 체크를 자동으로 처리해준다.
● 상품 상세 Form
상품 상세페이지 같은경우 체크부분을 클릭 가능하면 안된다.
따라서 disabled 를 사용해서 상품 상세에서는 체크 박스가 선택되지 않도록 했다.
<input type="checkbox" id="open" name="open" th:field="${item.open}" class="form-check-input" disabled>
다음 사진에서 확인해 보자.
'BackEnd > Thymeleaf' 카테고리의 다른 글
[Thymeleaf] 체크 박스 - 멀티 (0) | 2022.01.30 |
---|---|
[Thymeleaf] 입력 폼 처리 (0) | 2022.01.30 |
[Thymeleaf] 레이아웃 (0) | 2022.01.30 |
[Thymeleaf] 템플릿 조각 (0) | 2022.01.29 |
[Thymeleaf] 자바스크립트 인라인 (0) | 2022.01.28 |
댓글