Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Devoxx 2015: Thymeleaf: bridging the gap between designers and devs with server-side templates

Devoxx 2015: Thymeleaf: bridging the gap between designers and devs with server-side templates

Web application projects often have to deal with a mismatch between web design and software development. No matter whether these roles are taken by different teams, different people or simply different personalities of the same developer, there has always been conflict between the tools that bring data to the view layer and those in charge of representing such data in the most useful and visually appealing way.

Thymeleaf is a modern Java server-side template engine that aims at bringing together both worlds by allowing templates to be developed in a designer-friendly way, with maximum respect to HTML markup and minimum interference of template logic in design or prototyping artifacts.

As a plus, Thymeleaf's philosophy also allows the easy integration of client-side technologies like JavaScript libraries/frameworks so that developers can benefit from the best tools on the server and browser sides at the same time.

This talk will guide you through the capabilities of Thymeleaf and prepare you to start developing Thymeleaf templates, as well as show the new exciting features in Thymeleaf 3 that will make those already familiar with the project even more productive.

Daniel Fernández

November 09, 2015
Tweet

More Decks by Daniel Fernández

Other Decks in Technology

Transcript

  1. @danfenz #Devoxx #thymeleaf Bridging the gap between designers and devs

    with server-side templates Daniel Fernández http://www.thymeleaf.org | @thymeleaf
  2. @danfenz #Devoxx #thymeleaf •A template engine for Java •Open Source

    — Apache 2.0 License •First version 2011 — Currently 2.1.4, 3.0.0.BETA01 •It processes HTML, XML, JavaScript, CSS, text •Usually view layer in SpringMVC or MVC1.0 apps What is thymeleaf?
  3. @danfenz #Devoxx #thymeleaf <table> <thead> <tr> <th th:text="#{msgs.headers.name}">Name</th> <th th:text="#{msgs.headers.price}">Price</th>

    </tr> </thead> <tbody> <tr th:each="prod : ${allProducts}"> <td th:text="${prod.name}">Oranges</td> <td th:text="${#numbers.formatDecimal(prod.price,1,2}">0.99</td> </tr> </tbody> </table> What does it look like?
  4. @danfenz #Devoxx #thymeleaf “My HTML is not HTML anymore, but

    that's OK because the UI design phase is already finished.” Web developers, lying to themselves — since epoch.
  5. @danfenz #Devoxx #thymeleaf •Most times developers will do those…
 …restarting

    the app for each shade of blue •Yes, JRebel exists… but a running server still needed •More importantly: working Java code still needed •There must be a better way So, what about style changes?
  6. @danfenz #Devoxx #thymeleaf “Natural Templates: templates can be documents as

    valid as the final result, the engine syntax doesn't break the document structure.” “Comparison of web template engines” [Wikipedia]
  7. @danfenz #Devoxx #thymeleaf •Use non-standard attributes •Browsers ignore them •And

    they don't have influence on the DOM! The trick <ul> <li th:each="f : ${fruits}" th:text="${f.name}">Apricot</li> </ul>
  8. @danfenz #Devoxx #thymeleaf HTML5 allows custom attributes <ul> <li data-th-each="f

    : ${fruits}" data-th-text="${f.name}">Apricot</li> </ul> <ul> <li>Apricot</li> </ul> browser display equivalent
  9. @danfenz #Devoxx #thymeleaf Now we can prototype! <img src="../resources/images/logo.png" th:src="@{/images/logo.png}"/>

    <img src="../resources/images/logo.png"/> <img src="/myapp/images/logo.png"/> browser display equivalent output of running webapp
  10. @danfenz #Devoxx #thymeleaf •No need for double attributes: src +

    th:src, etc. •No need for prototyping text •Expression can be inlined Yet prototyping is very optional <tr> <td><img th:src="@{/images/logo.png}"/></td> <td>Welcome to our e-shop, [[${session.user.name}]].</td> </tr>
  11. @danfenz #Devoxx #thymeleaf •Write natural template prototypes for some pages

    •e.g. those that are most representative •Enough to conform a design agreement •Best: have the right tool to do what you please Virtue is in the middle (usually)
  12. @danfenz #Devoxx #thymeleaf Page composition / layout <div th:insert="footer ::

    copy">...</div> ... <div th:fragment="copy"> © 2015 The Great Great Web Developers </div> ... also th:include, th:replace somewhere in our footer.html
  13. @danfenz #Devoxx #thymeleaf Markup selectors <div th:replace="http://bannerserv.example.net/ :: div.banner">...</div> ...

    <div class="banner"> ... <img src="//somevendor/onegreatadd.png" width="168" height="80"/> ... </div> ... our banner server returns plain HTML (no th:fragment)
  14. @danfenz #Devoxx #thymeleaf Parameterizable fragments <div th:fragment="joiner (onevar, twovar)"> <p

    th:text="|${onevar} - ${twovar}|">...</p> </div> ... <div th:replace="::joiner (${user.name},${user.surname})">...</div> ... call fragment as if it were a function fragment can take parameters
  15. @danfenz #Devoxx #thymeleaf •Hierarchical layouts with the Layout Dialect •Apache

    Tiles 2 integration •thymol.js: JS library for static fragment insertion More on composition
  16. @danfenz #Devoxx #thymeleaf Text processing. And JS. And CSS. Dear

    [(${customer.name})], This is the list of our products: [# th:each="prod : ${products}"] - [(${prod.name})]. Price: [(${prod.price})] EUR/kg [/] Thanks, The Thymeleaf Shop new in Thymeleaf 3.0
  17. @danfenz #Devoxx #thymeleaf JavaScript natural templates var greeter = function()

    { var username = /*[[${session.user.name}]]*/ 'John Apricot'; alert('Hello ' + username); }; both <script> and .js files var greeter = function() { var username = 'Martin Grapefruit'; alert('Hello ' + username); }; processing result
  18. @danfenz #Devoxx #thymeleaf Decoupled templates(*) <table id="detail"> <tr> <td>Green Plum</td>

    <td>Round-oval shape and smooth-textured, pale green flesh</td> </tr> </table> <inject sel="#detail/tr" th:each="f : ${fruits}"> <inject sel="/td[0]" th:text="${f.name}"/> <inject sel="/td[1]" th:text="${f.description}"/> </inject> new in Thymeleaf 3.0 template logic, separate file (*) yet to be implemented as of 3.0.0.BETA01
  19. @danfenz #Devoxx #thymeleaf •Offline template processing (no Servlet API) •Full

    SpringMVC integration •Extensibility: dialects •Testability: automated testing for templates •Documentation •Tooling So many features, no time :(