Thymeleaf: create custom sections in default.html - java

Previously I have worked just with JSP and Apache Tiles and now I'm trying to create Thymeleaf template for the first time. The problem I faced is that I have no idea how to insert custom header, footer and other sections into default.html. Here is the code example.
default.html:
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8"/>
<title>Default template</title>
<link rel="stylesheet" type="text/css" href="../static/css/app.css" th:href="#{/css/app.css}"/>
<link rel="stylesheet" type="text/css" href="../static/css/bootstrap.css" th:href="#{/css/bootstrap.css}"/>
<link rel="stylesheet" type="text/css" href="../static/css/myCss.css" th:href="#{/css/myCss.css}"/>
</head>
<body>
<header id="header" layout:fragment="header">
HEADER
</header>
<section id="sidemenu" layout:fragment="sideMenu">
SIDE_MENU
</section>
<section id="site-content" layout:fragment="siteContent"></section>
<footer id="footer" layout:fragment="footerTemplate"></footer>
</body>
</html>
In default.html I have 'siteContent' which is provided for inserting all of application's html files, and 'header', 'sideMenu' and 'footer' sections that have to be implemented in separate corresponding html files (templates) and inserted into default.html.
index.html:
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="default">
<head>
<title>Index</title>
</head>
<body>
<div layout:fragment="siteContent">
<h1>Hello world!</h1>
</div>
</body>
</html>
footer.html:
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
<title>Footer Template</title>
</head>
<body>
<div layout:fragment="footer">
Copyright © 2017
</div>
</body>
</html>
This is an example of footer.
SiteContent area works fine. Footer's 'Copyright © 2017' is supposed to be imported into default.html's footer area, but it doesn't.

The solution is found: I should have used
'footer id="footer" layout:include="footerTemplate"'
instead of
'footer id="footer" layout:fragment="footerTemplate"'
By the way, the examples, listed on thymeleaf's website never worked, but the correct decision wasn't there.

Related

Is there a way to include CSS in a FreeMarker Email Template?

I am creating an email using Spring Boot and Apache FreeMarker. Is it possible to include CSS in the email without needing to have a huge tag in the header?
Here is an example .ftl file that I would like to link a .css file to:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<title>Hello, world!</title>
</head>
<body>
<div class="container">
<div class="style-in-css-doc">
Some text to be styled
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
You can simply include the css file into your template by putting css code in another ftl file and then include it to your main template with include directive
<#include path>

Render fragment contents with Thymeleaf

I'm tryting to have email templates rendered using Thymeleaf and I would like to have the subject and the body in the same file, but rendered separately. I do not want to use spring view, just plain SpringTemplateEngine.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!--/*#thymesVar id="user" type="com.myapp.user.User"*/-->
<!--/*#thymesVar id="invitationId" type="java.util.UUID"*/-->
<head>
<title th:fragment="subject">Hello <span th:text="${user.name}"/></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<p>
Hello <span th:text="${user.name}"></span>,<br>
you've been invited to join MyApp.
</p>
<p>
Click on the following link to confirm your email and setup a password:<br>
<a th:href="#{https://myapp.com/accept-invitation(id=${invitationId})}">Accept invitation</a>
</p>
<p>
Best regards,<br/>
<em>The MyApp team</em>
</p>
</body>
</html>
There are several problems with this
First, I'm unable to get Thymeleaf render only contents of <title>
String subject = templateEngine.process(
templateFile,
ImmutableSet.of("subject"),
new Context(Locale.ENGLISH, contextVariables)
);
it renders literary only Hello - it looks like the opening <title> tag is always removed and the fragment is trimmer right after the first tag.
And when I render the whole template, it returns
<!DOCTYPE html>
<html>
<head>
Hello <span>pepa</span></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<p>
Hello <span>pepa</span>,<br>
...
Using the following in the <title> makes the output a bit nicer
<span th:text="${user.name}" th:remove="tag"></span>
but the opening tag is still missing.
When I would theoretically succeed in rendering the title correctly, I'd still have it wrapped in an HTML tag - which obviously cannot be used as an email subject. Is there a way to render only contents of the fragment?
I would really like to have both the email subject and body in the same template for cases, when for example I want to do some iteration in the title to generate it from a list - I do not want to do any string concatenations, I wanna have it in the template.
Any suggestions please?
If you want to include only the content of your fragment, assuming that your fragment is called your_fragment.html and is placed under /resources/templates/fragments you can do:
<head>
<title th:replace="fragments/your_fragment::your_fragment"/></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
And your_fragment.html:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<div th:fragment="your_fragment" th:remove="tag">
Hello <span th:text="${user.name}" th:remove="tag"></span>
</div>
</body>
</html>
This will render:
<head>
Hello username
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>

Use config.properties in html

I made a config.properties file that sets a few things, including a webpage name. How do i access this webpage name when I am setting it inside of my html code?
Here is my config.properties file located in my resource directory in my java project.
port_number=8080
default_directory=/home/admin/Documents/archive
log_level= DEBUG
acceptable_extensions=.tar,.tar.gz,tar.tgz,.jar,.zip
DB_name= Thunder.db
title=Title
Then I have an html file called bootstrapPage.html also under my resource directory. Here is a bit of it... I want to use the title I set above in my config file inside this html file where it currently says "Project Thunder" if that is possible.
<html lang="en">
<head>
<script src="config.properties"></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>File Upload</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
<!-- creates top menu-->
<div class="container">
<nav class="navbar navbar-inverse">
<div class="navbar-header">
<a class="navbar-brand" href="#">Project Thunder</a>
</div>
</nav>
</div>

Does Thymeleaf have something like JSP tags?

I don't mean taglibs, I'm using a JSP tag to do something like this:
ChildPage.jsp:
<%# page contentType="text/html" pageEncoding="UTF-8" %>
<%# taglib prefix="t" tagdir="/WEB-INF/tags" %>
<t:layout>
<jsp:attribute name="head">
<link href="css/custom.css" type="text/css" rel="stylesheet"/>
</jsp:attribute>
<jsp:attribute name="scripts">
<script src="js/custom.js"></script>
</jsp:attribute>
<jsp:body>
<p>This is from the child page</p>
</jsp:body>
</t:layout>
layout.tag:
<%# tag description="Layout template" pageEncoding="UTF-8" %>
<%# attribute name="head" fragment="true" %>
<%# attribute name="scripts" fragment="true" %>
<!DOCTYPE html>
<html lang="en">
<head>
<link href="css/main.css" type="text/css" rel="stylesheet"/>
<jsp:invoke fragment="head"/>
</head>
<body>
<div id="body">
<p>This is from the parent or "layout"</p>
<jsp:doBody/>
</div>
<div id="footer">
<script src="js/main.js"></script>
<jsp:invoke fragment="scripts"/>
</div>
</body>
</html>
When rendered:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="css/main.css" type="text/css" rel="stylesheet"/>
<link href="css/custom.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<div id="body">
<p>This is from the parent or "layout"</p>
<p>This is from the child page</p>
</div>
<div id="footer">
<script src="js/main.js"></script>
<script src="js/custom.js"></script>
</div>
</body>
</html>
This allows me to include scripts in the header section of the JSP from both the layout and child pages. Same for the body and footer.
I've read through Thymeleaf docs/examples but maybe I'm not understanding correctly as it doesn't look like I can do what I am trying to achieve.
The reason why I have "inverted" what seems like a simple include is every page that I have includes certain scripts and a header section, but my child pages also have scripts to be imported and stylesheets to be included.
Can I achive this somehow? Am I doing this wrong?
By default Thymeleaf uses so called Include-style layouts. Disadvantages of this approach explained on official site. I would advise you to use Thymeleaf Layout Dialect. This is much more convenient dialect to create Hierarchical-style layouts.
By the way, in Layout Dialect all content of <head> tag will be merged automatically. Just take a look on example.

Thymeleaf namespace in html files display errors in Netbeans - How can I get it pass HTML checking?

Netbeans HTML checking doesn't like my thymeleaf namespace.
Here is my HTML Thymleaf file:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head">
<object th:include="fragments/meta :: meta" th:remove="tag" />
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Open+Sans:300italic,400,300,700' rel='stylesheet' type='text/css'/>
<link href="/../../../webjars/Semantic-UI/2.0.6/semantic.min.css" rel="stylesheet" th:href="#{/webjars/Semantic-UI/2.0.6/semantic.min.css}"/>
<link href="../../../css/core.css" rel="stylesheet" th:href="#{/css/core.css}" />
<link href="../../../css/product.css" rel="stylesheet" th:href="#{/css/product.css}" />
</head>
<body>
</body>
</html>
This is the error displayed in Netbeans:
How can I get Netbeans to play nicely with Thymeleaf?
Try to fix it in this way you may ignore spring security thing.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="utf-8"/>
<title>Sample</title>
<link th:href="#{/resources/css/bootstrap.css}" rel="stylesheet" type="text/css"/>
<link th:href="#{/resources/css/bootstrap-theme.css}" rel="stylesheet" type="text/css"/>
</head>
I found out how to disable these errors when I was taking this spring security tutorial
Simply by adding this to html tag:
xmlns="http://www.w3.org/1999/xhtml"
what's even cooler, netbeans now tracks if you closed every tag with slash "/" in document.

Categories