Skip to content

scrhartley/freemarker-fragments

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTML Fragments using FreeMarker Example

This is an example to emulate the benefits of fragments using the Java FreeMarker templating library. The main motivation to demonstrate this feature was to support use cases like htmx fragments.

Partial rendering

In order to render conditionally, macros are used in a component-like style (inspired by React). By taking advantage of FreeMarker macros being defined at parse time, not at process time, we can call them before their definition in the file.

Example with macro definitions omitted

    <!DOCTYPE html>
    <html>
    	<@Head />
    	<body>
    	    <@Menu />
    	    <@HeroBanner />
    	    <@Sidebar />
    	    <@MainContent />
    	    <@Footer />
    	</body>
    </html>

    <<<  macros go here  >>>

Fully automatic (Spring Boot implementation)

By using specific configuration, we can optionally specify a fragment identifier as part of the view name in the Controller.
e.g. return "myView :: MyFragment"; where the template is myView.ftlh and the macro to invoke is MyFragment.
Including the fragment identifier will cause the matching macro in that template to be invoked and only the output generated by that macro will be rendered.

When using the FullyAutomatic strategy, nothing special is required from the template or the Controller. If a fragment identifier is specified, then only the model attributes used by the selected macro are required (i.e. we avoid evaluating the full template).

Optionally (disabled by default), the code can automatically convert kebab-case and snake_case identifiers to match macros with UpperCamelCase/PascalCase names.
e.g. return "view :: my-fragment"; to invoke the macro MyFragment.

Manual/General Implementation Design Notes

See IMPL_NOTES for details of manual fragment handling as well as ideas about how to introduce limited automation for them.

Running

This is built using Spring Boot and so to start the server, either:

  • in your IDE, run the main method in FreeMarkerFragmentsApplication
  • as standalone:
    • either use ./mvnw spring-boot:run
    • or, build the project using ./mvnw clean package and then run the jar java -jar target/fragments.jar

Pages
The same pages exist for both implementations under /auto and /manual.

Simple page and a fragment of it (the article text):
http://127.0.0.1:8080/auto
http://127.0.0.1:8080/auto/fragment
http://127.0.0.1:8080/manual
http://127.0.0.1:8080/manual/fragment

Page with a table and also a single row as a fragment.
A single row's HTML would be useful when the client wants to add a completely new row. You can easily get the same HTML as for when you're rendering the whole table, without having to specify it more than once and then needing to keep both versions in sync.
http://127.0.0.1:8080/auto/table
http://127.0.0.1:8080/auto/table/row
http://127.0.0.1:8080/manual/table
http://127.0.0.1:8080/manual/table/row

About

Demo emulating template fragments using FreeMarker

Topics

Resources

Stars

Watchers

Forks