오봉이와 함께하는 개발 블로그
스프링 MVC 2 - 체크 박스 멀티 본문
체크 박스 - 멀티
체크 박스를 멀티로 사용해서, 하나 이상을 체크할 수 있도록 해보자.
- 등록 지역
- 서울, 부산, 제주
- 체크 박스로 다중 선택할 수 있다.
FormItemController - 추가
@ModelAttribute의 특별한 사용법
등록 폼, 상세화면, 수정 폼 모두에서 model
에 값을 담아주는 똑같은 코드가 필요하다.
이렇게 하면 필요한 컨트롤러(URL 매핑된 메서드)마다 코드를 반복해서 작성해야 하는 번거로움이 발생하는데 스프링에서 제공하는 기능을 사용해서 해결할 수 있다.
@ModelAttribute("regions")
public Map<String, String> regions() {
Map<String, String> regions = new LinkedHashMap<>();
// 서울, 부산, 제주 순서를 맞추기 위해 LinkedHashMap 사용
regions.put("SEOUL", "서울"); // key, value
regions.put("BUSAN", "부산");
regions.put("JEJU", "제주");
return regions;
}
@ModelAttribute
는 이렇게 컨트롤러에 있는 별도의 메서드에 적용할 수 있다.
이렇게 하면 해당 컨트롤러를 요청할 때 regions
에서 반환한 값이 자동으로 모델에 담기게 된다.@ModelAttribute("regions", regions);
로 담기게 된다.
물론 이렇게 사용하지 않고 각 컨트롤러 메서드마다 직접 담아서 사용해도 무방하다.
HTML
<!-- multi checkbox -->
<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>
<div th:each="region : ${regions}" class="form-check form-check-inline">
은 @ModelAttribute("regions")
의 regions
이다.
<input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input">
은 <form action="item.html" th:object="${item}" th:action method="post">
의 regions
다 (== ${item.regions}
)
멀티 체크박스는 같은 이름의 여러 체크 박스를 만들 수 있지만 이렇게 반복해서 HTML을 자동으로 생성할 때는 name
은 같아도 되지만, id
는 모두 달라야 한다.
따라서 타임리프는 체크박스를 루프 안에서 반복해서 만들 때 임의로 1
, 2
, 3
숫자를 뒤에 붙여준다.
th:for="${#ids.prev('regions')}"
위 코드를 보면 <label>
에 id
를 만들어줄 때 사용했다. #ids
를 사용하면 th:field="*{regions}"
를 보고 자동으로 생성된 id에 따라 <label>
태그에 id
를 넣어준다.
타임리프 HTML 생성 결과
<!-- 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>
<label for="id 값">
에 지정된 id
가 checkbox
에서 동적으로 생성된 regions1
, regions2
, regions3
에 맞추어 순서대로 입력된 것을 확인할 수 있다.
로그
FormItemController.addItem()에 코드를 추가하자.log.info("item.regions={}", item.getRegions());
서울, 부산 선택
HTTP 메시지 : regions=SEOUL&_regions=on®ions=BUSAN&_regions=on&_regions=on
로그 : item.regions=[SEOUL, BUSAN]
지역 선택X
HTTP 메시지 : _regions=on&_regions=on&_regions=on
로그 : item.regions=[]
_regions
는 웹 브라우저에서 체크를 하나도 하지 않았을 때, 클라이언트가 서버에 아무런 데이터를 보내지 않는 것을 방지한다
참고로 _regions
조차 보내지 않으면 결과는 null
이 된다._regions
가 체크박스 숫자만큼 생성될 필요는 없지만, 타임리프가 생성되는 옵션 수 만큼 생성해서 그런 것이다.
item.html - 추가
<!-- multi checkbox -->
<div>
<div>등록 지역</div>
<div th:each="region : ${regions}" class="form-check form-check-inline">
<input type="checkbox" th:field="${item.regions}" th:value="${region.key}" class="form-check-input" disabled>
<label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label>
</div>
</div>
주의 : item.html
에는 th:object
를 사용하지 않았기 때문에 th:field
부분에 ${item.regions}
으로 적어주어야 한다.disabled
를 사용해서 상품 상세에서는 체크 박스가 선택되지 않도록 하자.
타임리프의 체크 확인
멀티 체크 박스에서 등록 지역을 선택해서 저장하면, 조회시에 checked
속성이 추가된 것을 확인할 수 있다.
타임리프는 th:field
에 지정한 값과 th:value
의 값을 비교해서 체크를 자동으로 처리해준다.
editForm.html - 추가
<!-- multi checkbox -->
<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>
출처 : 인프런 김영한 지식공유자님 강의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
'BE > Thymeleaf' 카테고리의 다른 글
스프링 MVC 2 - 셀렉트 박스 (0) | 2022.08.18 |
---|---|
스프링 MVC 2 - 라디오 버튼 (0) | 2022.08.18 |
스프링 MVC 2 - 체크 박스 단일 (0) | 2022.08.17 |
스프링 MVC 2 - 요구사항 추가 (0) | 2022.08.17 |
스프링 MVC 2 - 입력 폼 처리 (0) | 2022.08.17 |