Thymeleaf to silnik szablonów, biblioteka napisana w JAVA. Umożliwia programistom zdefiniowanie szablonu strony HTML, XHTML lub HTML5, a następnie wypełnienie go danymi w celu wygenerowania końcowej strony. Dlatego też realizuje Model-View część Model-View-Controller wzorca.
Ważną zasadą projektową Thymeleaf jest to, że sam szablon musi być poprawnie napisany (X) HTML.
Wersja | Data | Najnowsze wydanie | Data |
---|---|---|---|
3.xx | 2016-05-08 | 3.0.6 | 2017-05-07 |
2.xx | 09.02.2012 | 2.1.5 | 11.07.2016 |
Aby przesłać formularz przez Ajax za pomocą Jquery:
<div id="yourPanel" th:fragment="yourFragment">
<form id="yourForm" method="POST"
th:action="@{/actions/postForm}"
th:object="${yourFormBean}">
<div class="form-group">
<label for="param1"></label>
<input class="form-component" type="text" th:field="*{param1}" />
</div>
<div class="form-group">
<label for="param2"></label>
<input class="form-component" type="text" th:field="*{param2}" />
</div>
<div class="form-group">
<label for="param3"></label>
<input class="form-component" type="checkbox" th:field="*{param3}" />
</div>
<button type="submit" class="btn btn-success">Save</button>
<a href='#' class="btn btn-default">Cancel</a>
</form>
</div>
<script th:inline="javascript">
/*<![CDATA[*/
$(document).ready(function () {
/*[+
var postUrl = [[@{/actions/postForm(
additionalParam=${#httpServletRequest.getParameter('additionalParam')}
)}]];
+]*/
$("#yourForm").submit(function (e) {
e.preventDefault();
$.post(postUrl,
$(this).serialize(),
function (response) {
var isErr = 'hasError';
// when there are an error then show error
if (response.indexOf(isErr) > -1) {
$("#yourPanel").html(response);
} else {
var formData = $("#yourForm").serializeArray(),
len = formData.length,
urlEnd = '';
for (i = 0; i < len; i++) {
urlEnd += formData[i].name + '=' + encodeURIComponent(formData[i].value) + '&';
}
/*[+
var urlReplacement = [[@{/another/page(
additionalParam=${#httpServletRequest.getParameter('additionalParam')}
)}]] + urlEnd;
+]*/
window.location.replace(urlReplacement);
}
}
);
return false;
});
});
/*]]>*/
</script>
Klasa YourFormBean:
@lombok.Getter
@lombok.Setter
@lombok.NoArgsConstructor
public class YourFormBean {
private String param1;
private String param2;
private boolean param3;
}
Kod kontrolera:
@RequestMapping(value = "/actions/postForm", method = RequestMethod.POST)
public String saveForm(Model model,
@RequestParam("additionalParam") Integer additionalParam,
@Valid @ModelAttribute("yourFormBean") YourFormBean yourFormBean,
BindingResult bindingResult,
RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
model.addAttribute("hasError", true);
return "your/template :: yourFragment";
}
redirectAttributes.addAttribute("additionalParam", additionalParam);
return "redirect:/another/page";
}
Aby rozpocząć pracę z Thymeleaf, odwiedź oficjalną stronę pobierania .
Zależność od Maven
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.1.RELEASE</version>
</dependency>
Stopniowa zależność
compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.1.RELEASE'
Przykładowa konfiguracja
Począwszy od wersji 3.0 Thymeleaf obsługuje tylko konfigurację Java.
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
resolver.setContentType("text/html; charset=UTF-8");
return resolver;
}
W viewResolver()
możesz ustawić np. Kodowanie i typ zawartości dla widoków. więcej informacji
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
W templateEngine()
możesz dodawać własne dialekty. Na przykład, aby dodać dialekt Spring Security, możesz to zrobić w ten sposób: engine.addDialect(new SpringSecurityDialect());
public ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
Spójrz na setter pod kątem przedrostka i przyrostka w metodzie templateResolver()
. Informuje Thymeleaf, że za każdym razem, gdy kontroler zwróci widok, Thymeleaf będzie szukał tych nazw, które html w katalogu webapp/views/
i dołącza sufiks .html
.
Przykład
@RequestMapping(value = "/")
public String homePage() {
return "foo/my-index";
}
Thymeleaf będzie szukał html o nazwie my-index.html
w katalogu webapp/views/foo/
. Zgodnie z powyższą przykładową konfiguracją.
Formularz obiektu
package formSubmission;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Kontroler
package formSubmission;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class FriendsController {
@GetMapping("/friends")
public String friendForm(Model model) {
model.addAttribute("personForm", new Person());
return "friendsForm";
}
@PostMapping("/friends")
public String submissionResult(@ModelAttribute("personForm") Person person) {
return "result";
}
}
friendsForm.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Friend form</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Friend Form</h1>
<form th:action="@{/friends}" th:object="${personForm}" method="post">
<p>Name: <input type="text" th:field="*{name}"/></p>
<p>Age: <input type="number" th:field="*{age}"/></p>
<p><input type="submit" value="Submit"/></p>
</form>
</body>
</html>
wynik.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Submission result</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>th:text="'My friend ' + ${personForm.name} + ' is ' + ${personForm.age} + ' years old'"</h1>
</body>
</html>
Jeśli chcesz wymienić części witryny, ajax jest łatwym sposobem.
Witryna.html, na której chcesz zastąpić treść na podstawie wybranej wartości:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Index</title>
</head>
<body>
<select id="selection">
<option>Content 1</option>
<option>Content 2</option>
</select>
<div id="replace_div">
Content goes here
</div>
<!-- JQury from Google CDN -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
//call function when page is loaded
getContent();
//set on change listener
$('#selection').change(getContent);
function getContent() {
//create url to request fragment
var url = /content/;
if ($('#selection').val() === "Content 1") {
url = url + "content1";
} else {
url = url + "content2";
}
//load fragment and replace content
$('#replace_div').load(url);
}
})
</script>
</body>
</html>
Oraz content.html z fragmentami, które chcesz dołączyć, na podstawie wybranej wartości:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<div th:fragment="content1">
This is Content 1
</div>
<div th:fragment="content2">
This is Content 2
</div>
</body>
</html>
Last but not least Spring MVC ContentController.java :
@Controller
@RequestMapping("content")
public class ContentController {
@RequestMapping("")
public String loadContent() {
return "website";
}
@RequestMapping("content1")
public String getContent1() {
return "content :: content1";
}
@RequestMapping("content2")
public String getContent2() {
return "content :: content2";
}
}
Przykładowa metoda w kontrolerze
@RequestMapping(value = "/test")
public String showCheckbox(Model model) {
boolean myBooleanVariable = false;
model.addAttribute("myBooleanVariable", myBooleanVariable);
return "sample-checkbox";
}
Zobacz: sample-checkbox.html
<input
type="checkbox"
name="myBooleanVariable"
th:checked="${myBooleanVariable}"/>
Nie używaj th:name
do checboxów, po prostu name