스프링/4. 스프링 MVC-2

20. 단일 체크박스

sdafdq 2023. 8. 26. 16:15
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes) {
    log.info("open = " + item.getOpen());

    Item savedItem = itemRepository.save(item);
    redirectAttributes.addAttribute("itemId", savedItem.getId());
    redirectAttributes.addAttribute("status", true);
    return "redirect:/form/items/{itemId}";
}

Post방식으로 /add로 들어올 시 수행

 

 

<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에서 체크박스를 체크 안하고 보내면 그냥 값이 없는거임. 그래서 위에서 log 찍은 거 보면 체크 안하고 보낼 시 null이라고 찍힘.

왜냐하면 사실 html에서 체크 여부는 checked=true 나 false 이런게 아니라 checked 자체가 있으면 체크된 거기 때문에 그냥 checked가 없다면 값이 없고 null이다.

 

그래서 이거는 스프링이 지원해주는건데,

input type="hidden" name="_원래체크박스이름" value="on"

하면 일단 on은 스프링에서 타입 컨버터 라는 곳에서 on이라는 문자열은 true로 변환해 줌. 

 

그리고 이게 중요한데,

저 위의 공식처럼 type hidden에 name을 _원래체크박스이름 value="on" 하면 

 

만약 체크를 하면 open과 _open이 같이 간다. 그런데 open에 값이 있으므로 _open은 버려지고 체크된걸로 인식한다.

 

만약 체크를 하지 않으면 type=hidden인 _open만 간다. 이렇다면 원래 있던 언더바를 뺀 open은 체크가 안되어 있는걸로 인식하고 false로 한다. 

 

 

타임리프를 통한 개선

타임리프에서 th:field는, id, name,value 뿐 아니라

checked가 적용되는 태그일 시 <input type=hidden name=_원래체크박스name> 도 함께 자동으로 넣어준다.

 

<div>판매 여부</div>
<div>
    <div class="form-check">
        <input type="checkbox" id="open" th:field="${item.open}" class="formcheck-input" disabled>
        <label for="open" class="form-check-label">판매 오픈</label>
    </div>
</div>

그래서 이렇게 간단하게 th:field 하나만 추가해서 쓸 수 있다.

 

마찬가지로 들어온 값(${item.open})이 true일 시 checked(정확히는 checked="checked")를 추가해주고 false일 시는 없에준다.