I am working in: “SpringMVC 5”, with “Twitter Bootstrap 4” html pages, and “Thymeleaf 3” templating, in IntelliJ EAP (latest version) and Tomcat9, Maven
The structure of my project:
src/main/java (WebConfig.java/Controlers/Beans) src/main/resources (*.properties) src/main/webapp/WEB-INF/views/layout/template.html src/main/webapp/WEB-INF/views/fragments/menubar.html src/main/webapp/WEB-INF/views/home.html (my page)
I am using these tutorials: https://www.baeldung.com/spring-thymeleaf-fragments https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#template-layout
I have my page (home.html). I have my template (template.html). According to the 2nd tutorial:
- I inserted the “menubar” into the “template” (this insert must work, because I inserted the menubar directly to the “home.html” and it was inserted successfuly)
- Question that I cannot solve from what they say into the 2nd tutorial: How I “decorate” my “home.html” according the “template.html”. I mean, how I use the template to decorate according it all my pages? I used the following in the “home.html” but it is not working:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/template}"
My files are:
“home.html”
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <!-- These in the html-tag are not working xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/template}" --> <body> <th:block th:fragment="page_content"> <!-- IntelliJ says I cannot recognise the th:block --> <h2>Home page</h2> <p>Hello home page</p> </th:block> </body></html>
“menubar.html”
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light" th:fragment="menubar"> <div class="container-fluid"> <!-- bla-bla --> </div> </nav> </body></html>
“template.html”
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <!-- Stylesheets (Bootstrap and mine) here --> <title>Template Title</title> </head> <body> <div th:replace="fragments/menubar.html :: menubar"></div> <!-- Page Content --> <section class="page_content"> <div layout:fragment="page_content"></div> </section> <!-- Javascript scripts (Bootstrap and mine) here --> </body></html>
“WebConfig.java”
@Configuration @ComponentScan(basePackages = {"packages"}) @EnableWebMvc public class WebConfig { /* I have a seperate controler that GETs my "home.html" successfuly */ @Bean public ViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".html"); viewResolver.setExposeContextBeansAsAttributes(true); return viewResolver; } @Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); //templateEngine.addDialect(new LayoutDialect()); // This is not working at all templateEngine.setTemplateResolver(thymeleafTemplateResolver()); return templateEngine; } @Bean public SpringResourceTemplateResolver thymeleafTemplateResolver() { SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); templateResolver.setTemplateMode("HTML5"); templateResolver.setPrefix("/WEB-INF/views/layout/"); templateResolver.setSuffix(".html"); return templateResolver; } @Bean public ThymeleafViewResolver thymeleafViewResolver() { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine()); return viewResolver; } }
In my pom (some of it):
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.12.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.0.12.RELEASE</version> </dependency> <dependency> <groupId>nz.net.ultraq.thymeleaf</groupId> <artifactId>thymeleaf-layout-dialect</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.4.RELEASE</version> </dependency> <dependency> <groupId>nz.net.ultraq.thymeleaf</groupId> <artifactId>thymeleaf-spring-environment-dialect</artifactId> <version>1.0.1</version> </dependency>
Please some one help. Thanks in advance
Advertisement
Answer
Hey finally I found solution:
Step 1
I put the page and the layout in the same folder:
src/main/webapp/WEB-INF/views/fragments/menubar.html src/main/webapp/WEB-INF/views/template.html src/main/webapp/WEB-INF/views/home.html (my page)
Step 2
In “home.html” I added the “layout:decorate”
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{template}"> ...
In “template.html” I changed the “layout:fragment”
<div th:replace="fragments/menubar.html :: menubar"></div> <!-- Page Content --> <section layout:fragment="page_content"> <p>Template content</p> </section>
In the “WebConfig.java” I deleted the “viewResolver() method” and I changed the others like following:
@Configuration @ComponentScan(basePackages = {"packages"}) @EnableWebMvc public class WebConfig { @Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.addDialect(new LayoutDialect()); // I added it again. Very important templateEngine.setTemplateResolver(thymeleafTemplateResolver()); return templateEngine; } @Bean public SpringResourceTemplateResolver thymeleafTemplateResolver() { SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); templateResolver.setTemplateMode("HTML"); templateResolver.setPrefix("/WEB-INF/views/"); templateResolver.setSuffix(".html"); return templateResolver; } @Bean public ThymeleafViewResolver thymeleafViewResolver() { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine()); return viewResolver; } }
But… A problem remains. I cannot keep my pages and my layout in different folders. If I do it with the previous structure and put: layout:decorate=”~{layout/template}” the page is displayed as a blank page.
Any solution and idea from you it would be perfect for me. A part of the solution is found though.
=========== Update: ===========
Solution in the last part is found. I had a mistake in the “template.html”. I should put it as: “layout/fragments/menubar.html :: menubar” with the structure:
src/main/webapp/WEB-INF/views/layout/template.html src/main/webapp/WEB-INF/views/fragments/menubar.html src/main/webapp/WEB-INF/views/home.html (my page)
And the code will be:
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <!-- Stylesheets (Bootstrap and mine) here --> <title>Template Title</title> </head> <body> <div th:replace="layout/fragments/menubar.html :: menubar"></div> <!-- Page Content --> <section class="page_content"> <div layout:fragment="page_content"></div> </section> <!-- Javascript scripts (Bootstrap and mine) here --> </body></html>
I will put it as a solution, in some hours when the system will let me.