🌿 Thymeleaf - Form 데이터 전솑 (Text, CheckBox, Multi Checkbox)

Kim Dae HyunΒ·2021λ…„ 7μ›” 22일
0

Thymeleaf

λͺ©λ‘ 보기
2/3
post-thumbnail

πŸš€
κ°„λ‹¨ν•œ Admin νŽ˜μ΄μ§€ μ •λ„λŠ” 슀슀둜 λ§Œλ“€ 수 μžˆλ„λ‘ ν…œν”Œλ¦Ώ 엔진을 κ³΅λΆ€ν•©λ‹ˆλ‹€ !

πŸ”Ž Text 데이터 전솑

κ°€μž₯ λ‹¨μˆœν•œ Text 데이터 전솑 μ˜ˆμ œμž…λ‹ˆλ‹€.

λ¨Όμ € Controller μΈ‘ μ½”λ“œμž…λ‹ˆλ‹€.
/test/form으둜 μš”μ²­μ΄ 왔을 λ•Œ 폼을 λ“€κ³ μžˆλŠ” viewλ₯Ό λžœλ”λ§μ‹œν‚€λŠ” λ©”μ„œλ“œλ₯Ό κ°–κ³  μžˆμŠ΅λ‹ˆλ‹€.

이 λ•Œ model에 빈 객체λ₯Ό λ„˜κΈ°λŠ”λ° 이 뢀뢄이 μ€‘μš”ν•©λ‹ˆλ‹€.

@Controller
@RequestMapping("/test")
public class TestController {

    @GetMapping("/form")
    public String showForm(Model model) {
        model.addAttribute("form", new FormDto());
        return "review/form";
    }
}

λ‹€μŒμœΌλ‘œ HTML μ½”λ“œμž…λ‹ˆλ‹€.
form νƒœκ·Έμ˜ μ†μ„±μœΌλ‘œ th:objectλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. th:object의 이름은 ${form}으둜 μ§€μ •ν•˜μ˜€κ΅¬μš”.

이 λ•Œ ${form}은 μ»¨νŠΈλ‘€λŸ¬μ—μ„œ λ„˜κ²¨μ€€ 빈 κ°μ²΄μž…λ‹ˆλ‹€.
thymeleafλŠ” μ΄λ ‡κ²Œ 빈 였브젝트λ₯Ό λ°›μ•„μ„œ 값을 μ„ΈνŒ…ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

th:object둜 빈 였브젝트λ₯Ό μ „λ‹¬λ°›μ•˜λ‹€λ©΄ μ•„λž˜ input νƒœκ·Έμ—μ„œ th:fieldλ₯Ό 톡해 ν•΄λ‹Ή 였브젝트의 ν•„λ“œμ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

th:field λŠ” μ΄λ ‡κ²Œ 객체의 ν•„λ“œμ— μ ‘κ·Όν•  수 μžˆλŠ” 것과 ν•¨κ»˜ μ—¬λŸ¬ 뢀가적인 κΈ°λŠ₯을 μ œκ³΅ν•΄μ£Όλ‹ˆ κΌ­ κΈ°μ–΅ν•΄μ•Ό ν•©λ‹ˆλ‹€. th:fieldλŠ” *{..} λ¬Έλ²•μœΌλ‘œ λ³€μˆ˜λ₯Ό 선택할 수 μžˆμŠ΅λ‹ˆλ‹€.
th:field="*{name}"은 model객체둜 μ „λ‹¬λœ form객체의 nameν•„λ“œμ— μ ‘κ·Όν•œλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€.

참고둜 th:action 뢀뢄에 μ•„λ¬΄λŸ° 섀정을 해주지 μ•Šμ•˜λŠ”λ° 이 λ•ŒλŠ” μ•„λž˜ 폼을 λžœλ”λ§ν•œ url둜 μš”μ²­ν•˜κ²Œ λ©λ‹ˆλ‹€.
ν˜„μž¬ GET /test/formμ—μ„œ μ•„λž˜ viewλ₯Ό λžœλ”λ§ ν•˜μ˜€μœΌλ‹ˆ form μš”μ²­ λ˜ν•œ POST /test/form으둜 κ°€κ²Œ λ©λ‹ˆλ‹€.
단, HTTPλ©”μ„œλ“œκ°€ λ‹€λ₯΄λ‹ˆ λ™μΌν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ§„ μ•ŠμŠ΅λ‹ˆλ‹€.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="../css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">

    <div class="py-4 text-center">
        <h2>Test Form</h2>
    </div>

    <form th:action th:object="${form}" method="post">
        <div>
            <label for="name">이름</label>
            <input type="text" id="name" th:field="*{name}" class="form-control">
        </div>

        <button class="btn-primary" type="submit">전솑</button>
    </form>
</div>
</body>
</html>

μ•„λž˜λŠ” 전솑에 μ‚¬μš©ν•œ κ°μ²΄μž…λ‹ˆλ‹€.

@Getter @Setter
public class FormDto {

    private String name;
}

이제 μ „μ†‘ν•΄λ³Όκ»˜μš”.

post μš”μ²­μ„ 받아쀄 컨트둀러 λ©”μ„œλ“œ μ½”λ“œμž…λ‹ˆλ‹€.
보톡 λ°›μ•„μ„œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μˆ˜ν–‰ 후에 λ‹€λ₯Έ λ·°λ₯Ό λžœλ”λ§ ν•˜κ±°λ‚˜ redirect ν•˜κ² μ§€λ§Œ κ°„λ‹¨ν•œ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ form으둜 λ‹€μ‹œ 데이터λ₯Ό μ „λ‹¬ν•©λ‹ˆλ‹€.

참고둜 Thymeleaf에 λŒ€ν•œ λ‚΄μš©μ€ μ•„λ‹ˆμ§€λ§Œ Model 객체λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  view 단에 데이터λ₯Ό λ„˜κΈΈ 수 μžˆλŠ” μ΄μœ λŠ” @ModelAttribute λ•λΆ„μž…λ‹ˆλ‹€. 이 μ–΄λ…Έν…Œμ΄μ…˜μ€ Model 객체λ₯Ό μƒμ„±ν•˜μ—¬ 전달받은 객체λ₯Ό λ„£μ–΄μ£ΌλŠ” μ—­ν• κΉŒμ§€ ν•΄μ€λ‹ˆλ‹€.

@PostMapping("/form")
public String form(@ModelAttribute("form") FormDto formDto) {

    return "review/form";
}

κ²°κ³Όλ₯Ό λ³΄μ‹€κ»˜μš”.
μ •μƒμ μœΌλ‘œ Text 데이터λ₯Ό μ „μ†‘ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


πŸ”Ž CheckBox 데이터 전솑

CheckBox λΆ€λΆ„ html μ½”λ“œμž…λ‹ˆλ‹€.
일반 text데이터λ₯Ό μ „μ†‘ν•˜λŠ” 것과 거의 λ™μΌν•©λ‹ˆλ‹€.

Thymeleaf의 th:fieldκ°€ μ—¬κΈ°μ„œ ꡉμž₯히 λ§Žμ€ 역할을 ν•΄μ€λ‹ˆλ‹€.
λ‚΄λΆ€μ μœΌλ‘œ hidden ν•„λ“œλ₯Ό λ§Œλ“€μ–΄μ„œ λ―Έμ²΄ν¬μ‹œ λ¬Έμ œκ°€λ˜λŠ” null 문제λ₯Ό ν•΄κ²°ν•΄μ£ΌλŠ” λ“±μ˜ 역할을 ν•΄μ€λ‹ˆλ‹€. λžœλ”λ§ 후에 λΈŒλΌμš°μ €μ—μ„œ μ†ŒμŠ€λ³΄κΈ°λ₯Ό ν•΄λ³΄μ‹œλ©΄ μž…λ ₯ν•˜μ§€ μ•Šμ€ νžˆλ“ νƒ€μž… μ²΄ν¬λ°•μŠ€κ°€ μΆ”κ°€λ˜μ–΄ μžˆμ„ 것 μž…λ‹ˆλ‹€.

<div>CheckBox Test</div>
<div>
	<div class="form-check">
		<input type="checkbox" th:field="*{tnf}" class="form-check-input">
		<label for="tnf" class="form-check-label">True or False</label>
	</div>
</div>

μš”μ²­ 객체λ₯Ό ν•œ 번 λ³Όκ»˜μš”.
νƒ€μž…μ€ κ°„λ‹¨ν•˜κ²Œ boolean으둜 ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.

@Data
public class FormDto {
    private String name;
    private boolean tnf;
}

ν…ŒμŠ€νŠΈ κ²°κ³Ό ( 체크 βœ”οΈ )

ν…ŒμŠ€νŠΈ κ²°κ³Ό ( λ―Έ 체크 ❌ )


πŸ”Ž Multi-Checkbox 데이터 전솑

multi-checkbox 데이터λ₯Ό λ°›κΈ° μœ„ν•œ ν•„λ“œλ₯Ό 폼 객체에 μΆ”κ°€ν•©λ‹ˆλ‹€.
μ—¬λŸ¬ 데이터가 λ“€μ–΄μ˜¬ 수 있기 λ•Œλ¬Έμ— List νƒ€μž…μœΌλ‘œ ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.

@Data
public class FormDto {
    private String name;
    private boolean tnf;
    private List<String> hobbies; // multi-checkbox
}

μ²΄ν¬λ°•μŠ€ keyκ°’κ³Ό value 값을 μ΄ˆκΈ°ν™”ν•˜μ—¬ Model 객체에 λ‹΄μ•„μ£ΌκΈ° μœ„ν•΄ λ©”μ„œλ“œ 레벨 @ModelAttribute λ₯Ό μ‚¬μš©ν• κ»˜μš”.
λ©”μ„œλ“œ 레벨 @ModelAttribute은 μ»¨νŠΈλ‘€λŸ¬μ— μž‘μ„±ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.
@ModelAttributeλ₯Ό λ©”μ„œλ“œ λ ˆλ²¨μ— 뢙이기 되면 λ¦¬ν„΄λ˜λŠ” 값을 @ModelAttribute("name") μ„€μ •ν•œ 이름을 keyκ°’μœΌλ‘œ ν•˜μ—¬ Model 객체에 λ‹΄μ•„μ€λ‹ˆλ‹€.
각 맀핑 λ©”μ„œλ“œμ—μ„œ model.addAttribute("hobbies", map); λ₯Ό ν•œ 것과 λ™μΌν•œ 것 μž…λ‹ˆλ‹€.

@ModelAttribute("hobbies")
private Map<String, String> favorite() {
    Map<String, String> map = new LinkedHashMap<>();
    map.put("movie", "μ˜ν™”λ³΄κΈ°");
    map.put("music", "μŒμ•…λ“£κΈ°");
    map.put("running", "λŸ°λ‹ν•˜κΈ°");
    map.put("game", "κ²Œμž„ν•˜κΈ°");
return map;
}

HTML 뢀뢄을 μž‘μ„±ν•΄μ€λ‹ˆλ‹€.
λ©”μ„œλ“œ 레벨 @ModelAttributeλ₯Ό 톡해 κ΅¬μ„±ν•œ map을 th:each λ₯Ό μ‚¬μš©ν•˜μ—¬ λ°˜λ³΅ν•˜λ©° ν•œ κ°œμ”© μ²΄ν¬λ°•μŠ€λ₯Ό λ§Œλ“€μ–΄μ€λ‹ˆλ‹€.
th:valueμ—λŠ” map의 key값이 λ‹΄κΈ°κ²Œ 되고 μ‹€μ œ μ„œλ²„λ‘œ μ „μ†‘λ˜λŠ” 값이 λ©λ‹ˆλ‹€.

label 의 forλΆ€λΆ„μ—μ„œ μƒμ†Œν•œ 문법이 μ‚¬μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
#{ids.prev('hobbies')} λŠ” th:field="*{hobbies}"에 μ˜ν•΄ λ™μ μœΌλ‘œ μƒμ„±λ˜λŠ” id 값에 λ§žμΆ°μ„œ 값을 μ„ΈνŒ…ν•΄μ£ΌλŠ” κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

μ•žμ„œ λ§ν–ˆλ“― th:fieldλŠ” idλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•΄μ€λ‹ˆλ‹€.
label의 forλŠ” input의 id와 λ°˜λ“œμ‹œ λ§žμΆ°μ€˜μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— μœ„μ™€ 같은 μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것 μž…λ‹ˆλ‹€.

#ids λŠ” νƒ€μž„λ¦¬ν”„κ°€ 자체적으둜 μ œκ³΅ν•˜λŠ” 객체둜 prev, next, seq λ“±μ˜ λ©”μ„œλ“œλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ μ‚¬μš©μžμ—κ²Œ 보여쀄 ν…μŠ€νŠΈλŠ” μ•žμ„œ κ΅¬μ„±ν•œ map의 value값을 μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
μžμ„Έν•œ 사항은 레퍼런슀λ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.

<hr class="my-4">
<div>
  <div>μ·¨λ―Έ 선택 (닀쀑 선택 κ°€λŠ₯)</div>
  <div th:each="hobby : ${hobbies}" class="form-check">
    <input type="checkbox" th:field="*{hobbies}" th:value="${hobby.key}" class="form-check-input">
    <label th:for="${#ids.prev('hobbies')}" th:text="${hobby.value}"  class="form-check-label"></label>
  </div>
</div>

λžœλ”λ§ κ²°κ³Όλ₯Ό ν•œ 번 λ³΄μ‹€κ»˜μš”.

데이터λ₯Ό μ „λ‹¬λ°›λŠ” 컨트둀러 μΈ‘μ—μ„œλŠ” λ™μΌν•˜κ²Œ 둜그만 μ°μ–΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

    @PostMapping("/form")
    public String form(@ModelAttribute("form") FormDto formDto) {
        log.info("formDto.name = {}", formDto.getName());
        log.info("formDto.tnf = {}", formDto.isTnf());
        List<String> hobbies = formDto.getHobbies();
        for (String hobby : hobbies) {
            log.info("formDto.hobby = {}", hobby);
        }

        return "review/form";
    }

κ²°κ³ΌλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

λ‹€μŒμ—λŠ” Radio Buttonκ³Ό Select Box에 λŒ€ν•΄ μ•Œμ•„λ³Όκ»˜μš”. κ°μ‚¬ν•©λ‹ˆλ‹€ πŸ™ƒ

profile
μ’€ 더 천천히 까먹기 μœ„ν•΄ κΈ°λ‘ν•©λ‹ˆλ‹€. 🧐

0개의 λŒ“κΈ€