[Thymeleaf] 체크박스, 라디오버튼, 셀렉트박스

HSRyuuu dev blog·2023년 4월 1일
0

타임리프(Thymeleaf)

목록 보기
9/9

체크박스 - 단일

1. (HTML)checkbox

객체에 open이라는 속성을 하나 추가했다.

체크박스는,
checked 상태에서는 open=true 을 반환하고,
unchecked 상태에서는 open=false를 반환하는 것이 대신, 아무것도 반환하지를 않는다.

그래서 open=null로 인식된다.

사실은 checked 상태에서는 open=on, unchecked 상태에서는 아무것도 반환하지 않는다. (null)
SpringBoot가 on을 true로 바꿔줘서, open=true 값을 받는 것이다.

물론 if(open==true) , else ~~ 이렇게 코딩할수도 있지만 귀찮기도 하고, 나중에 객체를 수정할 때는 아예 생성될때 open 속성이 존재하지 않았기 때문에 문제가 생길수도 있다.

따라서 html에서 히든 필드를 생성해 준다.


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

히든필드는 name에 체크박스의 name 앞에 언더바_를 추가해 준다. ( open → _open )

그렇게 되면 checked 상태에서는 open=on , _open=on을 둘 다 반환해서 SpringBoot가 open=true로 변환하고, _open은 없애버린다.

또한, unchecked 상태에서는 open=on은 반환하지 않고, _open=on 만을 반환해서,
SpringBoot가 open=false로 변환해준다.

이 과정에서 타임리프를 이용하면 조금 더 단순화 할 수 있다.


2. (thymeleaf)checkbox

th:object - th:field 를 사용하여 위의 예제를 바꿔준다.
(해당 <div> 태그의 상위태그에 th:object="${item}"가 포함되어 있다.)
<input>태그에 th:field="*{open}"를 추가해줘서 id, name 태그를 대체한다.

<div class="form-check">
	<input type="checkbox" id="open" th:field="*{open}" class="form-check-input">
	<label for="open" class="form-check-label">판매 오픈</label>
</div>

아래는 해당 페이지에서 ‘페이지 소스보기’ 한 결과이다.
th:field 기능을 쓰면, 체크박스 사용 시 타임리프가 히든필드를 자동으로 생성해 준다.

<input type="checkbox" id="open" class="form-check-input" name="open" value="true">
<input type="hidden" name="_open" value="on"/>



체크박스 - 멀티

하나의 공통된 클래스의 속성들 중 선택을 하는 다중 체크박스를 만들어 보자.

1. 멀티 체크박스를 위한 필드

우선, 해당 기능을 사용하는 모든 메소드에 regions라는 이름의 Map을 추가해준다.
그러나 아래처럼 똑같은 것을 반복해서 사용하는것은 좋지 않다.

	@GetMapping("/add")
    public String addForm(Model model){
        model.addAttribute("item",new Item());

		Map<String, String> regions = new LinkedHashMap<>();
        regions.put("SEOUL","서울");
        regions.put("BUSAN","부산");
        regions.put("JEJU","제주");

        return "form/addForm";
    }

메소드 레벨에서 @ModelAttribute를 사용할 수 있다.

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

컨트롤러에 위와 같은 메소드를 만들면, 해당 컨트롤러를 요청할 때, regions에서 반환한 값이
자동으로 model에 담기게 된다.
즉, 해당 컨트롤러 아래에 모든 메소드에서 세가지의 지역이 담긴 regions가 model에 담긴다.

물론, item 객체에 regions 속성이 있어야 한다.

public class Item {
	//생략
    private List<String> regions;
    //생략
}

2. 타임리프 적용

( <div>태그의 상위 태그에 th:object=”${item}”가 적용되어 있다. )

<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>
  1. th:each="region : ${regions}" : item의 regions에서 값을 하나씩 꺼내서 region에 담는다.

  2. *{regions}${item.regions}와 같다. )

  3. th:value="${region.key}" : region의 key가 th:value값이 된다.

  4. th:for="${#ids.prev('regions')}" : 동적으로 id를 생성시킨다.

    • 위의 th:field 의 regions를 이용해서 regions1, regions2 … 로 아이디를 자동으로 생성한다.
    • 그렇게되면 th:field에서 생성한 id=regions1이 th:for=”regions1”로 매칭된다.

위의 반복문을 통해 웹페이지에서 아래와 같은 html이 생성된다.

<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 ="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>



라디오 버튼

1. 객체에 속성 추가

라디오버튼에서 사용하기 위해 Item 클래스에 private ItemType itemType; 속성을 추가한다.

2. ENUM 생성

라디오 버튼은 여러 선택지중에 하나만 선택할 때 사용할 수있다.
BOOK, FOOD, ETC 세개의 속성을 가진 ENUM을 이용해보자.

public enum ItemType {
    BOOK("도서"), FOOD("음식"), ETC("기타");
    private final String description;
		//생성자, getter 생략
}

3. 컨트롤러 설정

컨트롤러에 @ModelAttribute를 메소드 레벨에 적용해서 사용할 수 있다.

	@ModelAttribute("itemTypes")
    public ItemType[] itemTypes(){
        ItemType[] values = ItemType.values();
        return ItemType.values();
    }

4. 라디오 버튼 html

        <div>
            <div>상품 종류</div>
            <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. 객체에 속성 추가

셀렉트 박스에서 사용하기 위해 Item 클래스에 private String deliveryCode; 속성을 추가한다.

2. 컨트롤러 설정

메소드 레벨에서 @ModelAttribute를 사용하여, deliverycode list를 만들어주자.

 	@ModelAttribute("deliveryCodes")
    public List<DeliveryCode> deliveryCodes(){
        List<DeliveryCode> deliveryCodes = new ArrayList<>();
        deliveryCodes.add(new DeliveryCode("FAST", "빠른 배송"));
        deliveryCodes.add(new DeliveryCode("NORMAL", "일반 배송"));
        deliveryCodes.add(new DeliveryCode("SLOW", "느린 배송"));
        return deliveryCodes;
    }

3. 셀렉트박스 html

<div>
	<div>배송 방식</div>
	<select th:field="*{deliveryCode}" class="form-select">
		<option value="">==배송 방식 선택==</option>
		<option th:each="deliveryCode : ${deliveryCodes}" 
           		th:value="${deliveryCode.code}" 
           		th:text="${deliveryCode.displayName}">FAST</option>
     </select>
</div>

(참고)김영한님 인프런 Spring MVC-2
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2

profile
Exciting dev life / 댓글, 피드백, 질문 환영합니다 !!!

0개의 댓글