I have freemarker template as below .
<!DOCTYPE html>
<html>
<head>
<title>My Blog</title>
</head>
<body>
<#if username??>
Welcome ${username} Logout | New Post
<p>
</#if>
<h1>My Blog</h1>
<#list myposts as post>
<h2>${post["title"]}</h2>
Posted ${post["date"]?datetime} <i>By ${post["author"]}</i><br>
Comments:
<#if post["comments"]??>
<#assign numComments = post["comments"]?size>
<#else>
<#assign numComments = 0>
</#if>
${numComments}
<hr>
${post["body"]!""}
<p>
<p>
<em>Filed Under</em>:
<#if post["tags"]??>
<#list post["tags"] as tag>
${tag}
</#list>
</#if>
<p>
</#list>
</body>
</html>
Where ${post["body"]!""} represents body of my blog and display.
My question : How to represent body tag as html content.
Example : if body has table string
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> ... " ,
then blog also represent same.
How to convert this string to html table.enter code here
Note: body may also have anything (dynamic) and body is not fixed one.
Related
In Freemarker, how can I create a template that inherits from a template that itself inherits?
Single inheritance works fine with the <#nested> tag:
File base.ftl:
<#macro layout>
<html lang="en">
<head>...</head>
<body>
<div>... (navigation bar)</div>
<div class="container">
<#nested>
</div>
</body>
</html>
</#macro>
File normalBase.ftl:
<#import "base.ftl" as base>
<#base.layout>
<div class="row">
<div class="col-md-9">
${content.body}
</div>
<div class="col-md-3">
<p>Latest releases</p>
<ul>....</ul>
</div>
</div>
</#base.layout>
How do I turn this into double inheritance where useCaseBase.ftl extends normalBase.ftl which extends base.ftl?
This works like a charm:
File base.ftl:
<#macro layout>
<html lang="en">
<head>...</head>
<body>
... // Shared navigation bar
<div class="container">
<#nested>
</div>
... // Shared footer
</body>
</html>
</#macro>
<#layout>
${content.body}
</#layout>
File normalBase.ftl:
<#import "base.ftl" as parent>
<#macro layout>
<#parent.layout>
<div class="row">
<div class="col-md-9">
<#nested>
</div>
<div class="col-md-3">
... // Shared sidebar
</div>
</div>
</#parent.layout>
</#macro>
<#layout>
${content.body}
</#layout>
File useCaseBase.ftl:
<#import "normalBase.ftl" as parent>
<#parent.layout>
${content.body}
... // Shared content between all use case pages
</#parent.layout>
Now I can create *.adoc pages with jbake-type set to either base, normalBase or useCaseBase and it works.
I tried to implement extends and block like Jinja2.
extends.ftl for defining macros.
<#if !blocks??>
<#assign blocks = {} />
</#if>
<#macro extends ftl>
<#nested />
<#include ftl />
</#macro>
<#macro replace name>
<#local value>
<#nested />
</#local>
<#assign blocks += {name: value} />
</#macro>
<#macro block name>
<#if blocks[name]??>
<!-- replaced ${name} -->
${blocks[name]}
<#else>
<!-- default ${name} -->
<#nested />
</#if>
</#macro>
base.ftl for layout
<#import "extends.ftl" as layout />
<!DOCTYPE html>
<html>
<head>
<title>A demo of FreeMarker extends directive</title>
</head>
<body>
<#layout.block "message">
This is default message in base.ftl
</#layout.block>
</body>
</html>
finally, index.ftl like this:
<#import "extends.ftl" as layout />
<#layout.extends "base.ftl">
<#layout.replace "message">
This is the message from index.ftl
</#layout.replace>
</#layout.extends>
Take a look at https://github.com/emesday/freemarker-extends .
Here is my Service ( It just gets a list of entities )
#Service
public class ProcedureService {
#Autowired
ProcedureRepository procedureRepository;
public List getProceduresList() {
List<Procedure> procedureList;
procedureList = procedureRepository.findAll();
return procedureList;
}
}
Here is my Controller. It just puts list he gets to view.
#Controller
public class ServicesController {
#Autowired
ProcedureService procedureService;
#GetMapping("/services")
public String getCustomer(Model model) {
List<Procedure> procedures = procedureService.getProceduresList();
model.addAttribute("procedures", procedures);
return "services";
}
}
And here is my real problem. Thyme leaf just doesn't see the entity in a List ( it sees the list though ). Here is my screen and full code of View
<!DOCTYPE html>
<html lang="en">
<head>
<title>SpringMVC + Thymeleaf + Bootstrap 4 Table Example</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1>Customer Table</h1>
<div class="row col-md-7 table-responsive">
<table id="customerTable" class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Age</th>
<th>Street</th>
<th>Postcode</th>
</tr>
</thead>
<tbody>
<tr th:each="procedure: ${procedures}">
<td th:text="${procedure.}" />
<td th:text="${procedure.getId}" />
</tr>
</tr>
</tbody>
</table>
</div>
</div>
I forgot about html lang="en" xmlns:th="http://www.thymeleaf.org" in html so th wasn't really working.
How to find out if a project is in debug mode and get a variable of a logical type in the freemarker template.
Example:
<#if (DEBUG)??>
<script src="/static/jquery/jquery.js"></script>
<#else>
<script src="/static/jquery/jquery.min.js"></script>
</#if>
I simplified the same using the equals operator:
<#if DEBUG == true>
<script src="/static/jquery/jquery.js"></script>
<#else>
<script src="/static/jquery/jquery.min.js"></script>
</#if>
I'm trying to include a letter head in my PDF templates like so:
fragments/header.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Header</title>
</head>
<body>
<div id="header" class="clearfix" th:fragement="header(sender, name, address1, address2, today)">
<div id="header-left">
<img class="logo" src="app/src/main/resources/template/pdf/assets/logo.png"/>
<div id="recipient">
<p th:object="${sender}"><span th:text="*{name}"></span> - <span th:text="*{address1short}"></span> - <span th:text="*{address2}"></span></p>
<p th:text="${name}"></p>
<p>
<span th:text="${address1}"></span><br/>
<span th:text="${address2}"></span>
</p>
</div>
</div>
<div id="header-right" th:object="${sender}">
<p><strong th:text="*{name}"></strong></p>
<p>
<span th:text="*{address1}"></span><br />
<span th:text="*{address2}"></span><br />
<span class="label" th:text="*{phoneLabel} + ':'"></span><span th:text="*{phone}"></span><br />
<span class="label" th:text="*{faxLabel} + ':'"></span><span th:text="*{fax}"></span><br />
<span class="label" th:text="*{emailLabel} + ':'"></span><span th:text="*{email}"></span><br />
<strong><span th:text="*{internetLabel}"></span>: <span th:text="*{internet}"></span></strong>
</p>
<p>
<span th:text="*{court}"></span><br />
<span th:text="*{registryNr}"></span><br />
<span th:text="*{directorLabel}"></span>: <span th:text="*{director}"></span><br />
<span th:text="*{vatId}"></span><br />
</p>
<p><span th:text="*{todayPrefix}"></span> <span th:text="${today}"></span></p>
</div>
</div>
</body>
</html>
template.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Template</title>
<link rel="stylesheet" type="text/css" media="all" href="app/src/main/resources/template/pdf/assets/style.css"/>
</head>
<body>
<div th:replace="app/src/main/resources/template/pdf/fragments/header :: header(${sender}, ${name}, ${address1}, ${address2}, ${today})"></div>
<!-- omitted for brevity -->
</body>
</html>
Everything works fine when I put the header code in the template directly. But when I try to inlude it as a fragment, like above, I get the following Error:
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "app/src/main/resources/template/pdf/fragments/header.html" - line 9, col 6)
template.html is in the app/src/main/resources/template/pdf/ folder. I had to include css and image files with the full path (from the root of the project) to get them to work. I tried including the fragment with the full path (as above) and only fragements/header, but I get the same error each time.
Im using
spring-boot-starter-thymeleaf 2.1.1
thymeleaf 3.0.11
Stacktrace:
[removed bc of character limit]
UPDATE
The correct path for the fragment is (in my case) "template/pfd/fragment/header" (so, full path from resources folder). Also, there was a typo in th:fragement="header".
The fragment reference should not be absolute to your project, but relative to your thymeleaf template root. So instead of (assuming it is app/src/main/resources/template/ whre your thymeleaf templates are located)
th:replace="app/src/main/resources/template/pdf/fragments/header ..."
use
th:replace="pdf/fragments/header ..."
The common use is
<div th:replace="fragments/header :: header"><div>
Using Thymeleaf
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Java, Spring Boot, FreeMarker</title>
<link href="/css/main.css" rel="stylesheet">
</head>
<script>
function myFunction() {
<#test/>
}
</script>
<body>
<h2>Java, Spring Boot, FreeMarker</h2>
<form action="/search" method="post">
Search : <input type="text" name="firstName" onkeyup="myFunction()" id = "fname">
<input type="submit" value="Submit">
</form>
<div style="background-color:lightblue">
<#macro test>
<#list empList as emp>
<div id="emp-data">
<ul>
<li>${emp}</li>
</ul>
</#list>
</div>
</#macro>
<script src="/js/main.js"></script>
</div>
</body>
When I run this code I am getting some errors on the browser console:
(index):60 Uncaught ReferenceError: myFunction is not defined at HTMLInputElement.onkeyup ((index):60) onkeyup # (index):60 – PCS 1 hour ago
Is it possible in FreeMarker to do something like that?
In a sense you can... but it doesn't do what you apparently believe it does. First all FreeMarker instructions, like <#test/>, are resolved on the server, then later the resulting output runs in the browser. So as far as the browser sees, function myFunction() { ... } contains HTML div-s directly in inside the { ... }, which is invalid JavaScript.