ํผ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ ํ๋ฉด ๊ณ์ธต๊ณผ ์๋น์ค ๊ณ์ธต์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ๋ค.
package jpabook.jpashop.controller;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotEmpty;
@Getter @Setter
public class MemberForm {
@NotEmpty(message = "ํ์ ์ด๋ฆ์ ํ์์
๋๋ค. ")
private String name;
private String city;
private String street;
private String zipcode;
}
package jpabook.jpashop.controller;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
@Controller
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@GetMapping("/members/new")
public String createForm(Model model){
model.addAttribute("memberForm", new MemberForm());
return "members/createMemberForm";
}
@PostMapping("/members/new")
public String create(@Valid MemberForm form, BindingResult result){
if(result.hasErrors()){
return "members/createMemberForm";
}
Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode());
Member member = new Member();
member.setName(form.getName());
member.setAddress(address);
memberService.join(member);
return "redirect:/";
}
}
@Valid ๋ค์ BindingResult result๊ฐ ์์ผ๋ฉด, ์ค๋ฅ ๋ฐ์ ์ ์ค๋ฅ๋ฅผ ๋ด์ ์ฑ๋ก ๋ค์ ์ฝ๋๋ฅผ ์คํ์ํจ๋ค.
<!DOCTYPE HTML>
<html xmlns:th="<http://www.thymeleaf.org>">
<head th:replace="fragments/header :: header" />
<style>
.fieldError {
border-color: #bd2130;
}
</style>
<body>
<div class="container">
<div th:replace="fragments/bodyHeader :: bodyHeader"/>
<form role="form" action="/members/new" th:object="${memberForm}"
method="post">
<div class="form-group">
<label th:for="name">์ด๋ฆ</label>
<input type="text" th:field="*{name}" class="form-control"
placeholder="์ด๋ฆ์ ์
๋ ฅํ์ธ์"
th:class="${#fields.hasErrors('name')}? 'form-control
fieldError' : 'form-control'">
<p th:if="${#fields.hasErrors('name')}"
th:errors="*{name}">Incorrect date</p>
</div>
<div class="form-group">
<label th:for="city">๋์</label>
<input type="text" th:field="*{city}" class="form-control"
placeholder="๋์๋ฅผ ์
๋ ฅํ์ธ์">
</div>
<div class="form-group">
<label th:for="street">๊ฑฐ๋ฆฌ</label>
<input type="text" th:field="*{street}" class="form-control"
placeholder="๊ฑฐ๋ฆฌ๋ฅผ ์
๋ ฅํ์ธ์">
</div>
<div class="form-group">
<label th:for="zipcode">์ฐํธ๋ฒํธ</label>
<input type="text" th:field="*{zipcode}" class="form-control"
placeholder="์ฐํธ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<br/>
<div th:replace="fragments/footer :: footer" />
</div> <!-- /container -->
</body>
</html>
ํธ๋ฌ๋ธ์ํ
/* Model ๊ฐ์ฒด ํ ํ๋ฆฟ ํ์ฑ ์ค๋ฅ */ org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing ( template: "class path resource [templates/members/createMemberForm.html]" )@GetMapping("/members/new") public String createForm(Model model){ model.addAttribute("memberForm", new MemberForm()); /* ํ ํ๋ฆฟ์์ ์ฐธ์กฐํ๋ ์์ฑ ์ด๋ฆ๊ณผ ์ปจํธ๋กค๋ฌ์์ Model ๊ฐ์ฒด์ ์ถ๊ฐํ ์์ฑ ์ด๋ฆ์ ์ ํํ๊ฒ ์ผ์นํด์ผ ํ๋ค. ๋์๋ฌธ์ ๊ตฌ๋ถ์ด ์ค์ํ๋ฏ๋ก ํ ํ๋ฆฟ์์ ${memberForm}์ด๋ผ๊ณ ์ ์๋ค๋ฉด, ์ปจํธ๋กค๋ฌ์์ model.addAttribute("memberForm", ...)๋ก ์์ฑ ์ด๋ฆ์ ์ผ์น์์ผ์ผ ํ๋ค. ์ด๋ ๊ฒ ํด์ผ Thymeleaf ํ ํ๋ฆฟ ์์ง์ด Model ๊ฐ์ฒด์์ ์ฌ๋ฐ๋ฅธ ์์ฑ์ ์ฐพ์ ์ฌ์ฉํ ์ ์๋ค. ์์ฑ ์ด๋ฆ์ด ์ ํํ ์ผ์นํ์ง ์์ผ๋ฉด, Thymeleaf๋ ํด๋น ์์ฑ์ ์ฐพ์ ์ ์์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.*/ return "members/createMemberForm"; }