Tìm hiểu về Form trong Thymeleaf
Đăng lúc: 10:30 PM - 18/03/2025 bởi Charles Chung - 279Trong bài viết này tôi sẽ hướng dẫn các bạn sử dụng Form trong Thymeleaf bao gồm submit dữ liệu trên form với GET/POST, binding dữ liệu từ đối tượng lên Form.

1. Giới thiệu
Trong Thymeleaf, form (biểu mẫu) là một phần quan trọng trong việc thu thập và gửi dữ liệu từ phía người dùng đến server. Thymeleaf cung cấp các thẻ đặc biệt như <form>
, <input>
, <textarea>
, <select>
, và nhiều thẻ khác để xây dựng các biểu mẫu dễ dàng và hiệu quả trong ứng dụng web. Đặc biệt, Thymeleaf hỗ trợ tích hợp chặt chẽ với Spring Framework, cho phép liên kết trực tiếp các đối tượng trong model với các trường dữ liệu của form, giúp việc xử lý và xử lý dữ liệu trở nên đơn giản hơn.
Một ví dụ cơ bản về form trong Thymeleaf:
1 2 3 4 5 6 7 8 9 |
<form th:action="@{/submit}" th:object="${user}" method="post"> <label for="name">Name:</label> <input type="text" th:field="*{name}" id="name"/> <label for="email">Email:</label> <input type="email" th:field="*{email}" id="email"/> <button type="submit">Submit</button> </form> |
Trong ví dụ trên:
th:action
định nghĩa URL gửi dữ liệu khi người dùng gửi biểu mẫu.th:object
liên kết biểu mẫu với đối tượng trong mô hình (ở đây là đối tượnguser
).th:field
liên kết từng trường trong biểu mẫu với các thuộc tính của đối tượng model (name
,email
).
Thymeleaf giúp dễ dàng xử lý các form, tự động điền giá trị vào các trường khi cần thiết, và cũng hỗ trợ kiểm tra lỗi (error handling) từ phía server một cách mượt mà.
2. Ví dụ
Trong ví dụ này chúng ta sẽ tạo 2 Form:
- Form submit get (tìm kiếm theo từ khóa)
- Form submit post (đăng ký user)
Bước 1: Tạo project springboot session3example1 với các dependency (xem bài 1)
Bươc 2: Tạo các package, classs và các view theo cấu trúc bên dưới
Bươc 3: Code lớp User (biểu diễn thông tin người dùng)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
package com.bkap.entities; import java.util.Date; public class User { private String name; private String email; private String password; private String gender; private String note; private boolean married; private Date birthday; private String profession; public User() { // TODO Auto-generated constructor stub } public User(String name, String email, String password, String gender, String note, boolean married, Date birthday, String profession) { super(); this.name = name; this.email = email; this.password = password; this.gender = gender; this.note = note; this.married = married; this.birthday = birthday; this.profession = profession; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } public boolean isMarried() { return married; } public void setMarried(boolean married) { this.married = married; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getProfession() { return profession; } public void setProfession(String profession) { this.profession = profession; } } |
Bươc 4: Code lớp HomeController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package com.bkap.controllers; import java.util.Arrays; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import com.bkap.entities.User; @Controller public class HomeController { //đáp ứng request get localhost:8080 @GetMapping("/") public String index(Model model) { return "index"; } //đáp ứng request get localhost:8080/search @GetMapping("/search") public String index(Model model,String search) { model.addAttribute("msg","Kết quả tìm kiếm từ"); model.addAttribute("name",search); return "result"; } //đáp ứng request get localhost:8080/register @GetMapping("/register") public String showForm(Model model) { var user=new User(); user.setGender("Male"); user.setMarried(true); List<String> listprofession=Arrays.asList("Developer","Tester","Architect","Designer"); model.addAttribute("user",user); model.addAttribute("listprofession",listprofession); return "register"; } //đáp ứng request post localhost:8080/register @PostMapping("/register") public String register(Model model, User user) { model.addAttribute("user",user); return "success"; } } |
Bươc 5: Code view index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Gửi nhận dữ liệu</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" /> </head> <body> <div class="container"> <h1>Xử lý dữ liệu trên FORM</h1> <p> <b>Gửi request GET từ form tới controller</b> </p> <form action="/search" method="GET"> Nhập tên cần tìm <input type="text" name="search" /> <button>Tìm</button> </form> <p> <b><a href="/register">Đăng ký ngay</a></b> </p> </div> </body> </html> |
Bươc 6: Code view result.html
1 2 3 4 5 6 7 8 9 10 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>[[${msg}]]</title> </head> <body> <h1><span th:text="${msg+':'+name}"></span></h1> </body> </html> |
Bươc 7: Code view register.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Đăng ký thành viên</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" /> </head> <body> <div class="container"> <h1>Đăng ký thành viên</h1> <hr /> <form action="#" th:action="@{/register}" method="post" th:object="${user}"> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="name">Họ và tên</label> <div class="col-sm-10"> <input type="text" th:field="*{name}" class="form-control" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="email">E-mail:</label> <div class="col-sm-10"> <input type="text" class="form-control" th:field="*{email}" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="password">Mật khẩu:</label> <div class="col-sm-10"> <input type="password" th:field="*{password}" class="form-control" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="birthday">Ngày sinh (y/m/d):</label> <div class="col-sm-10"> <input type="text" class="form-control" th:field="*{birthday}" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="gender">Giới tính:</label> <div class="col-sm-10"> <input type="radio" th:field="*{gender}" value="Male" /> Male <input type="radio" th:field="*{gender}" value="Female" /> Female </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="profession">Nghề nghiệp:</label> <div class="col-sm-10"> <select class="form-control" th:field="*{profession}"> <option th:each="p:${listprofession}" th:value="${p}" th:text="${p}" /> </select> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="married">Có gia đình?</label> <div class="col-sm-10"> <input type="checkbox" th:field="*{married}" /> </div> </div> <div class="form-group row"> <label class="col-sm-2 col-form-label" for="note">Ghi chú:</label> <div class="col-sm-10"> <textarea rows="5" cols="25" th:field="*{note}" class="form-control"></textarea> </div> </div> <button class="btn btn-primary" type="submit">Đăng ký</button> </form> </div> </body> </html> |
Bươc 8: Code view success.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Đăng ký thành công</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" /> </head> <body> <div class="container"> <h1>Thông tin đăng ký</h1> <div th:object="${user}"> <p> Họ và tên: <span th:text="*{name}"></span> </p> <p> Email: <span th:text="*{email}"></span> </p> <p> Mật khẩu: <span>*******</span> </p> <p> Giới tính: <span th:text="*{gender}"></span> </p> <p> Ngày sinh: <span th:text="*{#dates.format(birthday, 'dd-MM-yyyy')}"></span> </p> <p> Nghề nghiệp: <span th:text="*{profession}"></span> </p> <p> Ghi chú: <span th:text="*{note}"></span> </p> <a href="javascript:history.back()">Quay lại</a> </div> </div> </body> </html> |
Bước 9: Chạy và xem kết quả
- Submit form GET
- Submit form Post
Source tải tại đây
3. Video demo (sẽ quay buổi dạy lớp C2308G)
thay lời cảm ơn!
Các bài cũ hơn
- Giới thiệu và cài đặt Thymeleaf trong Eclipse (09:58 PM - 16/03/2025)
- Tìm hiểu về Spring Boot MVC (10:01 AM - 15/03/2025)
- Hướng dẫn cài đặt môi trường phát triển ứng dụng web với Spring Boot 3 sử dụng Eclipse trên Windows (11:27 AM - 13/03/2025)
- Review đồ án kỳ 4 - Flutter Mobile App lớp C2303LM Bách Khoa Aptech (02:40 PM - 12/03/2025)
- Review đồ án SEM IV-App Đọc truyện online với Flutter Group3-C2110I2 Bách Khoa Aptech (09:53 AM - 20/10/2024)