π
κ°λ¨ν Admin νμ΄μ§ μ λλ μ€μ€λ‘ λ§λ€ μ μλλ‘ ν
νλ¦Ώ μμ§μ 곡λΆν©λλ€ !
κ°μ₯ λ¨μν 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 λΆλΆ 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
λ°μ΄ν°λ₯Ό λ°κΈ° μν νλλ₯Ό νΌ κ°μ²΄μ μΆκ°ν©λλ€.
μ¬λ¬ λ°μ΄ν°κ° λ€μ΄μ¬ μ μκΈ° λλ¬Έμ 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
μ λν΄ μμλ³Όκ»μ. κ°μ¬ν©λλ€ π