Skip to content

BlackPepperSoftware/thymeleaf-fragment.js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

thymeleaf-fragment.js

Process Thymeleaf fragments in the browser.

Thymeleaf promotes the use of natural templates that can be viewed in the browser as static prototypes. This works well for the majority of Thymeleaf attributes but falls down when using template fragments. Third-party tools such as Thymol do solve this problem but they also process the entire template which can be a hindrance.

To address this thymeleaf-fragment.js provides a simple script that only processes th:include, th:insert and th:replace attributes using jQuery.

Getting started

Include jQuery and the script within your template:

<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js"
	defer="defer" th:if="false"></script>

The th:if attributes cause the scripts to be included when prototyping but not at runtime. defer will execute the script once the document has finished loading. If you include any other scripts that rely on fragments then ensure that they are included after thymeleaf-fragment.js.

Using fragments

Once thymeleaf-fragment.js has been included in your template simply use the regular Thymeleaf th:insert attribute to insert a fragment:

<html>
	<body>
		<div th:insert="fragments::helloworld"></div>
	</body>
</html>

This will look for the template fragments.html and find the named fragment helloworld:

<html>
	<body>
		<p th:fragment="helloworld">Hello world!</p>
	</body>
</html>

And then append its content to the <div> to produce:

<html>
	<body>
		<div>
			<p>Hello world!</p>
		</div>
	</body>
</html>

To replace the <div> with the fragment instead use the Thymeleaf th:replace attribute. The deprecated th:include attribute is also supported. See the Thymeleaf documentation for more details about the fragment syntax.

Demo

View the demo to see a live example of processing fragments.

Browser restrictions

When prototyping templates locally fragments are loaded from the local file system. Browsers will typically disallow this since cross origin requests are denied for the file: protocol. This security constraint can be relaxed to allow fragments to be loaded correctly. For example, when using Chrome relaunch the browser using:

google-chrome --allow-file-access-from-files

Note that this is not required if you preview the templates directly from an IDE such as IntelliJ IDEA. This is because the templates are loaded from IntelliJ IDEA's local HTTP server and not the local file system.

Alternatively, you may wish to use a tool like live-server to serve up your local files through a local HTTP server.

Resolving templates

On the server-side Thymeleaf uses the ITemplateResolver interface to resolve template names into resources. For the client-side thymeleaf-fragment.js takes the following approach:

  1. Prepend the template prefix (nothing by default) and append the template suffix (.html by default) to the template name
  2. Resolve the resultant relative URL against the document's base URL to obtain an absolute URL

For example, consider how a template file:///app/template.html that inserts the fragment fragments::helloworld is resolved: firstly, the fragment's template name fragments is converted into the relative URL fragments.html; then it is resolved against the template's base URL file:///app/template.html to obtain file:///app/fragments.html.

When templates are organised in a hierarchy use the <base> HTML element to define the base URL for fragments. For example, given the following file structure:

app/
+- admin/
|  +- widgetsView.html
+- widget/
   +- widget.html

The template widgetsView.html can define app/ to be the base URL for the fragment widget.html as follows:

<html>
	<head>
		<base href="../" th:if="false"/>
	</head>
	<body>
		<div th:insert="widget/widget::widget"></div>
	</body>
</html>

The th:if attribute causes the template's base URL to be set when prototyping but not at runtime.

Configuration

To specify the prefix and suffix used for template resolution, use data-template-prefix and data-template-suffix attributes on the script tag in your template.

Consider a standard Spring Boot application, with a directory structure as follows:

resources/
+- templates/
|  +- page.html
|  +- fragments.html
+- static/
   +- logo.png

The base URL is set to correctly to load static content (images, stylesheets and fonts), and the template prefix locates the template relative to this.

<base href="../static/" th:if="false"/>
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js"
	data-template-prefix="../templates/" data-template-suffix=".html"
	defer="defer" th:if="false"></script>

Build Status