오봉이와 함께하는 개발 블로그

스프링 MVC 2 - 체크 박스 멀티 본문

BE/Thymeleaf

스프링 MVC 2 - 체크 박스 멀티

오봉봉이 2022. 8. 17. 22:17
728x90

체크 박스 - 멀티

체크 박스를 멀티로 사용해서, 하나 이상을 체크할 수 있도록 해보자.

  • 등록 지역
    • 서울, 부산, 제주
    • 체크 박스로 다중 선택할 수 있다.

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 값">에 지정된 idcheckbox에서 동적으로 생성된 regions1, regions2, regions3에 맞추어 순서대로 입력된 것을 확인할 수 있다.

로그

FormItemController.addItem()에 코드를 추가하자.
log.info("item.regions={}", item.getRegions());

서울, 부산 선택

HTTP 메시지 : regions=SEOUL&_regions=on&regions=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편 - 백엔드 웹 개발 활용 기술
728x90

'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
Comments