체크박스 - 2. 멀티 체크박스

알파로그·2023년 3월 25일
0

Spring MVC 활용 기술

목록 보기
22/42

🔗 요구사항 확인

✏️ 멀티 체크박스 구현

  • 배송 가능지역을 멀티 체크박스기능을 사용해 구현해야 한다.

📍 Controller - 계층

  • 순서를 보장받기 위해 LinkedHashMap 을 사용했다.
  • @ModelAttribute
    • 이 어노테이션이 선언된 method 를 생성하면 해당 Controller 내의 모든 매핑 Method 의 model 에 반환값이 전달된다.
    • @ModelAttribute 의 매개변수가 Web 계층에서 사용할 변수명이다.

⚠️ 성능 최적화를 위해선 이 Method 를 static 영역에 생성후 필요할 때만 호출하는 방법이 더 효과적이다.

  • 이 방법은 필요하지 않을 때도 계속 호출이 된다.
  • 하지만 지금 방식이 성능에 크게 영향을 미치지는 않는다.
@Slf4j
@Controller
@RequestMapping("/form/items")
@RequiredArgsConstructor
public class FormItemController {

    private final ItemRepository itemRepository;

    @ModelAttribute("regions")
    public Map<String, String> regions() {
        Map<String, String> region = new LinkedHashMap<>();
        region.put("SEOUL", "서울");
        region.put("BUSAN", "부산");
        region.put("JEJU", "제주");
        return region;
    }

📍 Web 계층 - item 등록

  • 여러개의 체크박스를 만들기 위해 each 문을 사용했다.
  • input 에 filed 속성은 Entity 와 연결해야 되기 때문에 Entity 의 필드값이다.
    • value 속성은 param 으로 보내야 되기 때문에 map 의 key 값이다.
    • value 의 값이 param 으로 넘어와 Entity 의 List region 에 저장된다.
  • label 의 th:text 속성에서 설정해준 map 의 value 가 체크박스의 이름으로 랜더링 된다.
  • ${#ids.prev('...')}
    • th:field 는 each 문 내에 설정될 경우 index 마다 동적으로 id, name 을 바꿔주는데,
      for 속성과 매핑되기위해 field 의 동적 id 값을 구해주는 기능이다.
<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-inline"></label>
</div>

📍 소스 확인

  • th:field
    • id 가 겹치지 않게 동적으로 생성되었다.
    • 히든 필드를 생성해 false 가 정상적으로 출력되게 만들었다.
    • name 은 중복되어도 상관없다.
  • th:for="${#ids.prev('...')}"
    • 인덱스마다 바뀌는 id 값을 for 와 잘 매핑시켰다.
  • th:text
    • map 의 value 값을 라벨에 랜더링 시켰다.
<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-inline">서울</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-inline">부산</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-inline">제주</label>
</div>

📍 log 확인

  • 3 항목 모두 체크후 등록하니 배열의 형태로 정상적으로 parameter 가 전달 되었다.
    • value 로 선언한 map 의 key 값이 message body 로 잘 요청됨
INFO 45865 --- [nio-8080-exec-1] h.i.web.form.FormItemController          
		: item.regions = [SEOUL, BUSAN, JEJU]
  • 항목을 모두 체크하지 않는다면 히든 필드에 의해 빈 배열이 정상적으로 전달된다.
INFO 45865 --- [nio-8080-exec-1] h.i.web.form.FormItemController          
		: item.regions = []

✏️ 수정, 조회 추가

  • 나머지 수정, 조회 페이지에도 로직을 추가해주면 된다.
<!-- edite -->
<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-inline"></label>
</div>

<!-- itme -->
<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-inline"></label>
</div>
profile
잘못된 내용 PR 환영

0개의 댓글