코드 그라데이션

Thymeleaf 통합 (5) 라디오 버튼 본문

Spring/Thymeleaf

Thymeleaf 통합 (5) 라디오 버튼

완벽한 장면 2023. 12. 6. 16:25

라디오 버튼

라디오 버튼은 여러 선택지 중에 하나를 선택할 때 사용할 수 있다. 

라디오 버튼을 자바 ENUM을 활용해서 개발한다.

 

상품 종류

  • 도서, 식품, 기타
  • 라디오 버튼으로 하나만 선택할 수 있다.

 

FormItemController - 추가

// @ModelAttribute 어노테이션이 적용된 메서드
// 이 메서드는 "itemTypes"라는 이름으로 모델에 데이터를 추가한다.
@ModelAttribute("itemTypes")
public ItemType[] itemTypes() {
    // ItemType 열거형(enum)의 모든 값을 배열로 반환.
    // ItemType.values() 메서드는 enum에서 정의한 모든 열거 상수를 배열로 제공.
    return ItemType.values();
}
  • itemTypes 를 등록 폼, 조회, 수정 폼에서 모두 사용하므로 @ModelAttribute 의 특별한 사용법을 적용하자.
  • ItemType.values() 를 사용하면 해당 ENUM의 모든 정보를 배열로 반환한다. 예) [BOOK, FOOD, ETC]

 

부연

1.

- @ModelAttribute("itemTypes"): 이 어노테이션은 메서드가 모델에 데이터를 추가하도록 지정한다. 

- "itemTypes"는 모델에 데이터를 추가할 때 사용되는 이름. 

   이 이름을 통해 뷰 템플릿에서 이 데이터에 접근할 수 있다.

 

2. 

- public ItemType[] itemTypes(): 이 메서드는 itemTypes()라는 이름을 가진 공개(public) 메서드. 

- 이 메서드는 @ModelAttribute 어노테이션이 적용되어 있어서 

  Spring MVC에서 컨트롤러가 요청을 처리할 때 자동으로 호출된다.

 

3. 

- return ItemType.values();: 이 메서드는 ItemType이라는 열거형(enum)의 모든 값을 배열로 반환한다. 

- ItemType 열거형은 어떤 항목의 종류를 나타내는 상수들을 정의한 것으로, 

  이 메서드는 이러한 상수들을 배열로 만들어 모델에 추가한다. 

- 따라서 뷰 템플릿에서 "itemTypes"라는 이름으로 이 배열을 사용할 수 있다.

 


상품 등록 폼에 기능을 추가한다.

addForm.html - 추가

<!-- radio button -->
<div>
    <!-- "상품 종류" 섹션을 표시하는 div -->
    <div>상품 종류</div>

    <!-- Thymeleaf 반복문을 사용하여 각 상품 종류에 대한 라디오 버튼을 생성 -->
    <div th:each="type : ${itemTypes}" class="form-check form-check-inline">
        <!-- 라디오 버튼 입력 요소 -->
        <input type="radio" th:field="*{itemType}" th:value="${type.name()}"
               class="form-check-input">

        <!-- 라디오 버튼 레이블 요소 -->
        <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
               class="form-check-label">BOOK</label>
    </div>
</div>

 

실행하면

1

새로운 메뉴가 생겼고

 

 

페이지 소스 보기 누르면

2

 

로그 찍기 위해 addItem() 에 코드 추가

log.info("item.itemType={}", item.getItemType());
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes) {

    log.info("item.open={}", item.getOpen());
    log.info("item.regions={}", item.getRegions());
    log.info("item.itemType={}", item.getItemType());

    // 상품 정보를 데이터베이스에 저장하고 저장된 상품 정보를 반환.
    Item savedItem = itemRepository.save(item);

    // 리다이렉트 시 URL에 파라미터를 추가하기 위해 RedirectAttributes를 사용.
    // "itemId" 파라미터에 저장된 상품의 ID를 추가.
    redirectAttributes.addAttribute("itemId", savedItem.getId());

    // "status" 파라미터를 추가하고 값을 true로 설정. (예: 성공적으로 상품을 추가한 상태를 나타냄)
    redirectAttributes.addAttribute("status", true);

    // 상품 추가 후 해당 상품의 상세 정보 페이지로 리다이렉트.
    return "redirect:/form/items/{itemId}";
}

 

이제 다시 실행해서 확인해보자.

(역시 빠른 파악을 위해 디버그 모드 잠시 중지.)

1

이렇게만 하고 등록하면

2

BOOK 이 나온다.

 

 

체크 안하고 등록하면

3
4

그냥 null 이 나온다.

 

얘는 히든 필드를 만들지 않는다.

비워도 된다.

 

 


 

상품 상세와 수정에도 라디오 버튼을 넣기

item.html

<!-- 추가 -->
<!-- radio button -->
<div>
    <div>상품 종류</div>
    <div th:each="type : ${itemTypes}" class="form-check form-check-inline">
        <input type="radio" th:field="${item.itemType}" th:value="${type.name()}" class="form-check-input" disabled>
        <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
               class="form-check-label">
            BOOK
        </label>
    </div>
</div>

 

실행해서 확인하면

등록을 이렇게 했다고 하면

 

페이지 소스 보기에서

 

 

수정

editForm.html 에도 추가

<!-- 추가 -->
<!-- radio button -->
<div>
    <div>상품 종류</div>
    <div th:each="type : ${itemTypes}" class="form-check form-check-inline">
        <input type="radio" th:field="${item.itemType}" th:value="${type.name()}" class="form-check-input" disabled>
        <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
               class="form-check-label">
            BOOK
        </label>
    </div>
</div>

 

등록을 이렇게 했으면

 

수정을 눌렀을 때

다른 필드와 달리 null 값으로 남겨둘 수가 없음.

그래서 히든 필드가 굳이 필요하지 않는 것임.

 

 


타임리프에서 Enum 직접 사용하기

<div th:each="type : ${T(hello.itemservice.domain.item.ItemType).values()}"> 이 문법을 쓰면 된다.

<!-- radio button -->
<div>
    <div>상품 종류</div>
    <div th:each="type : ${T(hello.itemservice.domain.item.ItemType).values()}" class="form-check form-check-inline">
        <input type="radio" th:field="*{itemType}" th:value="${type.name()}"
               class="form-check-input">
        <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
               class="form-check-label">
            BOOK
        </label>
    </div>
</div>

이걸 쓰면 모델에서 얘를 굳이 안 담아와도 된다.

패키지 아동 등의 변수에 귀찮고 힘들어짐.

 

728x90
Comments