BAEL-1562 - Working with Fragments in Thymeleaf (#3868)
* BAEL-1562 - Thymeleaf sample working * BAEL-1562 Code added for Fragments sample * BAEL-1562 - Last correction for the test * BAEL-1562 - Thymeleaf sample working * BAEL-1562 Code added for Fragments sample * BAEL-1562 - Last correction for the test
This commit is contained in:
parent
b20a3a1097
commit
5edb9acb95
|
@ -27,3 +27,6 @@ http://localhost:8082/spring-thymeleaf/addStudent/
|
|||
http://localhost:8082/spring-thymeleaf/listStudents/
|
||||
|
||||
The first URL is the home page of the application. The home page has links to the other two pages.
|
||||
|
||||
### Security
|
||||
The user/password required is: user1/user1Pass
|
||||
|
|
|
@ -142,7 +142,8 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application
|
|||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
|
||||
registry.addResourceHandler("/resources/**", "/css/**")
|
||||
.addResourceLocations("/WEB-INF/resources/", "/WEB-INF/css/");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.thymeleaf.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import com.baeldung.thymeleaf.utils.StudentUtils;
|
||||
|
||||
@Controller
|
||||
public class FragmentsController {
|
||||
|
||||
@GetMapping("/fragments")
|
||||
public String getHome() {
|
||||
return "fragments.html";
|
||||
}
|
||||
|
||||
@GetMapping("/markup")
|
||||
public String markupPage() {
|
||||
return "markup.html";
|
||||
}
|
||||
|
||||
@GetMapping("/params")
|
||||
public String paramsPage() {
|
||||
return "params.html";
|
||||
}
|
||||
|
||||
@GetMapping("/other")
|
||||
public String otherPage(Model model) {
|
||||
model.addAttribute("data", StudentUtils.buildStudents());
|
||||
return "other.html";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
body {
|
||||
background-color: lightGray
|
||||
}
|
||||
|
||||
.dark {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.light {
|
||||
background-color: #f1f1f1;
|
||||
color: #ccc;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Thymeleaf Fragments: home</title>
|
||||
<!--/*/ <th:block th:include="fragments/general.html :: headerfiles"></th:block> /*/-->
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<p>Go to the next page to see fragments in action</p>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<div th:fragment="formField (field, value, size)">
|
||||
<div>
|
||||
<label th:for="${#strings.toLowerCase(field)}"> <span
|
||||
th:text="${field}">Field</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:id="${#strings.toLowerCase(field)}"
|
||||
th:name="${#strings.toLowerCase(field)}" th:value="${value}"
|
||||
th:size="${size}">
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head th:fragment="headerfiles">
|
||||
<meta charset="UTF-8" />
|
||||
<link th:href="@{/css/styles.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div th:fragment="header">
|
||||
<h1>Thymeleaf Fragments sample</h1>
|
||||
</div>
|
||||
<p>Go to the next page to see fragments in action</p>
|
||||
<aside>
|
||||
<div>This is a sidebar</div>
|
||||
</aside>
|
||||
<div class="another">This is another sidebar</div>
|
||||
<footer th:fragment="footer">
|
||||
<a th:href="@{/fragments}">Fragments Index</a> |
|
||||
<a th:href="@{/markup}">Markup inclussion</a> |
|
||||
<a th:href="@{/params}">Fragment params</a> |
|
||||
<a th:href="@{/other}">Other</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
<div th:fragment="dataPresent">Data received</div>
|
||||
<div th:fragment="noData">No data</div>
|
|
@ -0,0 +1 @@
|
|||
<div><p id="parag">This is a subtitle</p></div>
|
|
@ -0,0 +1,14 @@
|
|||
<table>
|
||||
<thead th:fragment="fields(theadFields)">
|
||||
<tr th:replace="${theadFields}">
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody th:fragment="tableBody(tableData)">
|
||||
<tr th:each="row: ${tableData}">
|
||||
<td th:text="${row.id}">0</td>
|
||||
<td th:text="${row.name}">Name</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
</tfoot>
|
||||
</table>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Thymeleaf Fragments: markup</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<div th:replace="fragments/general.html :: aside"></div>
|
||||
<div th:replace="fragments/general.html :: div.another"></div>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Thymeleaf Fragments: other</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:replace="fragments/general.html :: header"> </header>
|
||||
<div
|
||||
th:replace="${#lists.size(data) > 0} ?
|
||||
~{fragments/menus.html :: dataPresent} :
|
||||
~{fragments/menus.html :: noData}">
|
||||
</div>
|
||||
<table>
|
||||
<thead
|
||||
th:replace="fragments/tables.html :: fields(~{ :: .myFields})">
|
||||
<tr class="myFields">
|
||||
|
||||
<th>Id</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<div
|
||||
th:replace="fragments/tables.html :: tableBody(tableData=${data})"></div>
|
||||
</table>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Thymeleaf Fragments: params</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<div
|
||||
th:replace="fragments/forms.html :: formField(field='Name', value='John Doe',size='40')">
|
||||
</div>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,90 @@
|
|||
package com.baeldung.thymeleaf.controller;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.baeldung.thymeleaf.config.InitSecurity;
|
||||
import com.baeldung.thymeleaf.config.WebApp;
|
||||
import com.baeldung.thymeleaf.config.WebMVCConfig;
|
||||
import com.baeldung.thymeleaf.config.WebMVCSecurity;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class })
|
||||
public class FragmentsTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
@Autowired
|
||||
MockHttpSession session;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private Filter springSecurityFilterChain;
|
||||
|
||||
private RequestPostProcessor testUser() {
|
||||
return user("user1").password("user1Pass").roles("USER");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build();
|
||||
}
|
||||
@Test
|
||||
public void whenAccessingFragmentsRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/fragments").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<title>Thymeleaf Fragments: home</title>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAccessingParamsRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/params").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<span>Name</span>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAccessingMarkupRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/markup").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<div class=\"another\">This is another sidebar</div>")));
|
||||
}
|
||||
@Test
|
||||
public void whenAccessingOtherRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/other").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<td>John Smith</td>")));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue