Aleš Woska
2.2.2017

ThymeLeaf – Jak na něj?

thymeleaf

Thymeleaf je javovský server- side templatovací engine. V příspěvku si ukážeme, jak jej připojit do projektu, na příkladech si ukážeme jeho možnosti použití a jak jednoduše implementovat typické problémy. Ukážeme si také pár složitějších problémů a jejich řešení. Nakonec si shrneme jeho klady a zápory.

Anotace:

This contribution concerns Thymeleaf which is a Java server-site template engine. In this contribution we demonstrate a basic usage of Thymeleaf – how to integrate it to a project, it’s basic possibilities and how to implement common issues easily. Next, we demonstrate some tricks and how to solve some advanced issues. At the end we enumerate some advantages and disadvantages of Thymeleaf.

Thymeleaf

 

Integrace do projektu

Thymeleaf si dobře rozumí se Springem, proto jej můžeme známým způsobem zaintegrovat do projektu pomocí Configuration beany nebo pomocí XML kontextu. Nakonfigurovat potřebujeme minimálně 2 povinné objekty – TemplateEngine a TemplateResolver. Z příkladu je patrné, že budoucí Thymeleaf šablony budeme ukládat do adresáře WEB-INF/templates s příponou .html.

Configuration bean

ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
templateResolver.setCacheable(true);
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);

XML Context

<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
 <property name="templateMode" value="HTML5" /> <property name="characterEncoding" value="UTF-8" /> <property name="cacheable" value="false"/> <property name="cacheTTLMs" value="1" /> <property name="order" value="100"/> <property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix" value=".html" /> </bean>
<bean id="templateEngine" class="org.thymeleaf.TemplateEngine">
 <property name="templateResolvers">
 <set>
 <ref bean="templateResolver" />
 </set>
 </property>
</bean>

spring a thzmeleaf

Langtexty

Texty samozřejmě nechceme mít v naší šabloně nakódované napevno, proto si můžeme nastavit načítání textů z klasických langtext souborů. Nastavení je jednoduché – stačí připojit již existující springovský message resolver k thymeleafovskému template enginu.

Configuration bean

templateEngine.setMessageResolver(messageResolver);

XML Context

<bean id="o4DefaultThymeleafEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
 <property name="messageResolvers">
 <set>
 <bean ref="messageResolver" />
 </set>
 </property>
</bean>

Co se týká základního nastavení, je to vše. Kdybychom chtěli nastavit specifičtější vlastnosti, Thymeleaf má slušnou dokumentaci: http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html, kde jsou popsány další možnosti nastavení.

Základní konstrukty

Konstrukty Thymeleafu se používají principiálně přidáním určitých atributů s prefixem th: do HTML tagů. Hodnoty z langtext souborů se vkládají pomocí #{nazev.property}, hodnoty z proměnných se vkládají pomocí ${nazevPromenne}. Následuje několik nejpoužívanějších a zajímavých konstruktů.

  • Obyčejný span element s textem
<span th:text=”#{some.text.property}” />
  • Podmíněné zobrazení elementu s textem:
<div th:if=”${value == 100}” th:text=”${name}” >puvodni_text</div>

Text uvnitř DIVu puvodni_text je nahrazen obsahem proměnné name. Celý DIV se zobrazí, jen pokud je hodnota proměnné value rovna sto. Když podmínka splněna není, element se vůbec nezobrazí. Pokud chceme negativní podmínku, můžeme použít negaci th:if=”${!expr}” nebo můžeme použít attribut th:unless, který element zobrazí, pokud podmínka není splněna.

  • Cyklus
<select>
 <option th:each=”car: ${cars}” th:value=”${car}” th:text=”${car}”></option>
</select>

Atribut th:each definuje proměnnou cyklu car. Její viditelnost je v elementu OPTION a všech jeho podelementech. Její hodnotu používáme pro zobrazení textu uvnitř elementu OPTION a také pro definování atributu VALUE.

  • Definování proměnné
<form th:with=“help = ${allhelps.first.help}“>
 <input type=“text“ id=“example“ name=“example“ value=““ />
 <label for=“example“ th:text=“${help}“></label>
</form>

Atribut th:with definuje proměnnou help, která je viditelná uvnitř element FORM, včetně podelementů. Všimneme si tečkové notace, pomocí které můžeme k vlastnostem objektu. Můžeme volat také metody objektu. Abychom si ušetřili tečkovou notaci, můžeme použít následující konstrukt, který definuje referovaný objekt a na jeho property se odkazujeme pomocí výrazu *{}:

<form th:object=“${formObject}“>
 <input type=“text“ th:field=“*{firstName}“ />
 <input type=“text“ th:field=“*{lastName}“ />
 <input type=“date“ th:field=“*{birthDate}“ />
</form>

Objekt formObject obsahuje 3 property, na které se odkazujeme přes *{}. Zajímavý je také atribut th:field, který prováže pole s hodnotou proměnné. Taktéž pro input definuje atributy name a id, vše automaticky. Po submitu formuláře jsou v objektu nastaveny zadané hodnoty.

  • Custom atribut
<table th:attr=”data-table-test = ${someData}”>…</table>

Tento konstrukt způsobí, že element TABLE bude obsahovat atribut data-table-test s hodnotou uvnitř proměnné someData.

  • „Skrytý“ element

Chceme-li použít nějaký element pro účely thymeleafu (např. pro cyklus, definici proměnné), ale nechceme element zobrazit na stránce, můžeme jej skrýt – zobrazí se jen jeho obsah, ale definované proměnné zůstávají platné.

<div th:with=”value = ${some.object.value}” th:remove=”tag”>
 <div th:text=“${value}“ />
</div>

V tomto příkladu zůstane na stránce pouze jeden element DIV, jehož obsahem bude obsah proměnné value. Totožnou funkci splní tento konstrukt:

<th:block th:with=”value = ${some.object.value}”>
 <div th:text=“${value}“ />
</th:block>

Ecosystem_official_image_eclipse_plugin

 Záludné problémy

S těmito několika konstrukty vystačíme na velkou část problémů. Občas ale nastanou různé situace, které nelze triviálně vyřešit a je třeba znát nějaké triky.

  • Hodnota proměnné v JavaScriptu
<script th:inline="javascript">
 /*<![CDATA[*/
 alert([[${message}]]); 
 /*]]>*/
</script>

Při použití JS v Thymeleaf šabloně musíme jeho obsah oescapovat – to je ta krásná část s CDATA v HTML komentáři. Vložení Thymeleaf proměnné do JS provedem dvojitou hranatou závorkou [[${promenna}]].

  • Langtext dle hodnoty proměnné
<label th:utext="#{__${labelResource}__}"></label>

Chceme použít langtext, ale jeho kód neznáme předem, protože je uložený v proměnné. V tomto případě jsme použili tzv. preprocesing pomocí dvou podtržítek, použití je zřejmé z příkladu. Můžeme jít ještě o krok dále – přistoupit na proměnnou, jejíž název je uložen v jiné proměnně:

<div with=“test = *{__${var_name}__}“></div>
  • Podmíněné přidání třídy elementu
<input th:classappend="${ajaxUpdate} ? 'ajax-validated'" />

Element INPUT bude mít třídu „ajax-validated“, pouze pokud hodnota proměnné „ajaxUpdate“ je true. Všimneme si trojitého operátoru, v Thymeleafu můžeme druhou část za „:“ vynechat.

  • Práce se Stringy, seznamy a hashmapami

S hashmapou pracujeme intuitivně – můžeme volat metodu .get() a při práci se seznamem můžeme používat indexy. Můžeme se k nim chovat, jako k javovským objektům, takže můžeme volat také metody jako .size() a nebo také statické metody jiných objektů, jako lists.isEmpty() nebo (tentokrát ohledně Stringu) strings.isEmpty():

<span th:if="${not #strings.isEmpty(textToDisplay)}"></span>
<section th:unless="${#lists.isEmpty(order.vouchers)}">…</section>
<p th:with="subscriber = ${subscriberList[0]}">…</p>
<span th:text="${countryNames.get(country)}"></span>

Proč používat Thymeleaf

Dobrá integrace se Springem. Natural templating – šablony mohou sloužit jako funkční prototypy a jsou zobrazitelné i bez předzpracování.

Osobní názor – rychlý a efektivní na naučení, přehledná syntaxe, dobře se s ním pracuje.

Proč nepoužívat Thymeleaf

Více dialektů šablonovacího jazyka. Omezený jen na XML a HTML. Rychlost – u příliš velkých stránek má Thymeleaf problémy s  rychlostí. U „normálních“ stránek ale na problémy s výkonem nenarazíme.

Vaše emailová adresa nebude zveřejněna

Komentáře

Děkujeme za váš komentář
Další
  • Tomáš Piňos

    Poslední dva odstavce mají v nadpisu chybu (LIferay místo Thymeleaf).

    1. Monika Vavrikova

      díky, ano. Opravili jsme :)

  • Martin

    V poslednich dvou nadpisech mate uvedeno "Liferay", spravne ma byt "Thymeleaf". :-)

    1. Monika Vavrikova

      děkujeme, opraveno :)

  • Michal

    V sekci: Integrace do projektu->XML Context Nemělo by být namísto uvedeno ? Stejně tak na id="templateEngine" aby to odpovídalo Java zápisu. Případně to je potřeba upravit i v sekci Langtexty->XML Context

    1. Monika Vavrikova

      Děkujeme za komentář, autor udělal v článku změnu