SlideShare a Scribd company logo
1 of 53
Download to read offline
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka 
Maciej Ziarko 
14.10.2014
Dowiecie się, czym jest i co potrafi Thymeleaf 
Wykonacie kilka ćwiczeń w webowym tutorialu 
Będziecie mogli jutro z marszu wykorzystać Thymeleaf we własnym projekcie 
Dowiecie się, gdzie poszerzyć swoją wiedzę, gdy zajdzie taka potrzeba 
Cel dzisiejszego spotkania?
Potężny silnik szablonów, potrafiący generować dokumenty XML/XHTML/HTML5 
Szablony są poprawnymi dokumentami XML/XHTML/HTML5 
Wiele dialektów (możliwość tworzenia własnych) 
Twórcy biblioteki zapewniają integrację ze Spring MVC i Spring Security 
Wysoka wydajność dzięki mechanizmowy pamięci podręcznej 
Czym jest Thymeleaf?
Jak działa Thymeleaf?
Jak to wygląda w Spring MVC? 
@RequestMapping("/somePage") String showSomePage(Model model) { model.addAttribute("key1", new Value1()) model.addAttribute("key2", new Value2()) return "templateName" } 
Dzięki integracji ze Spring MVC i auto-konfiguracji w Spring Boot proces z poprzedniego slajdu może być zupełnie transparentny dla programisty
Przykład prostego szablonu 
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <body> <p th:text="#{wjug.welcome}"> Welcome to WJUG! </p> </body> </html>
Informacje potrzebne bibliotece przekazywane są przy pomocy atrybutów, a nie tagów 
Czołowe przeglądarki ignorują nieznane przez siebie atrybuty 
Natural Templating – szablony, które mogą być jednocześnie prototypem, który można uruchomić w przeglądarce bez przetwarzania 
Zupełnie inaczej jest w przypadku większości popularnych dawniej technologii szablonowych: JSP, Freemarker, Velocity itd. 
Analiza prostego szablonu
Thymeleaf jest bardzo elastyczny – rozszerzalny przy pomocy nowych dialektów 
Silnik szablonów może korzystać jednocześnie z wielu dialektów 
Głównym składnikiem dialektu są procesory, które wiedzą, jak interpretować poszczególne atrybuty 
Można tworzyć nowe dialekty w oparciu o istniejące 
Najpopularniejsze dialekty: Standard, Spring Standard, Spring Security, Layout 
Dialekty
th:text 
<p th:text="#{wjug.welcome}"> 
Welcome to WJUG! 
</p> 
Wylicza wartość wyrażenia i zastępuje nią wnętrze tagu 
Wyliczona wartość może być bezpiecznie umieszczona w dokumencie HTML (escaping) 
wjug.welcome=Witamy na WJUG! 
W pliku messages_pl.properties:
th:utext 
<p th:utext="#{wjug.welcome}"> Welcome to <strong>WJUG</strong>! </p> 
Czasem może zdarzyć się, że z jakiegoś powodu escaping nie jest pożądany 
wjug.welcome=Witamy na <strong>WJUG</strong>! 
W pliku messages_pl.properties:
Składnia wyrażeń - ${…} 
<span th:text="${user.name}"> j_kowalski </span> 
${…} oblicza wartość na podstawie zmiennych znajdujących się w kontekście
Dostęp do elementów mapy, pól obiektów… 
map['key'] map.key 
Wyciąganie elementów mapy: 
Wyciąganie pól z obiektów: 
object['field'] object.field 
Wołanie metod: 
person.countDebt() 
Elementy listy/tablicy: 
people[2]
Składnia wyrażeń - #{…} 
<p th:text="#{wjug.welcome(${user.name})}"> 
Welcome to WJUG, Johnny Kowalski! 
</p> 
#{…} jest wykorzystywane do internacjonalizacji – wartość jest ustalana na postawie Locale oraz plików properties 
wjug.welcome=Witamy na WJUG, {0}! 
W pliku messages_pl.properties:
Składnia wyrażeń - @{…} 
@{…} jest wykorzystywane do tworzenia odnośników 
Szczególnie przydatne dla th:href 
W przypadku web aplikacji dodaje do odnośnika ścieżkę kontekstową 
Umożliwia ustawianie parametrów
Dla aplikacji ze ścieżką kontekstową /app zostanie zmienione na: 
@{…} – ścieżka kontekstowa 
<a href="profile.html" th:href="@{/profile}"> profile </a> 
<a href="/app/profile"> profile </a>
@{…} - parametry 
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}"> 
view 
</a> 
Dla o.id równego 100 zostanie zamienione na: 
<a href="/app/order/details?orderId=100"> 
view 
</a>
@{…} - parametry 
@{/order/process(execId=${execId},execType='FAST')} 
Można ustawić kilka parametrów na raz: 
A także parametryzować zmienne wewnątrz ścieżki: 
@{/order/{orderId}/details(orderId=${o.id})}
Konkatenacja łańcuchów znaków 
th:text="'The name of the user is ' + ${user.name}" 
Łańcuchy znaków można konkatenować korzystając z operatora +: 
Można też skorzystać ze specjalnej składni literal substitutions: 
th:text="|Welcome to our application, ${user.name}!|"
Czas na pierwsze ćwiczenie 
http://itutorial.thymeleaf.org/exercise/1 
Ćwiczenie znajduje się pod adresem:
th:object i *{…} 
th:text="${product.description}" 
th:text="${product.price}" 
Atrybut th:object oraz *{…} pozwalają ulepszyć nasz kod: 
Jako dobrzy inżynierowie nie lubimy duplikacji: 
<dl th:object="${product}"> <dt>Product name</dt> <dd th:text="*{description}">...</dd> </dl>
Rozwiążmy lepiej ćwiczenie pierwsze 
http://itutorial.thymeleaf.org/exercise/1 
Ćwiczenie znajduje się pod adresem:
Utility Objects 
#dates 
#calendars 
#numbers 
Obiekty, posiadające pomocnicze metody: 
Głównie przydają się do różnego rodzaju formatowania: 
${#numbers.formatInteger(num,3)} ${#numbers.formatDecimal(num,3,2)} ${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
Czas na drugie ćwiczenie 
http://itutorial.thymeleaf.org/exercise/2 
Ćwiczenie znajduje się pod adresem:
Ustawianie wartości atrybutów 
Thymeleaf umożliwia wstawianie wartości dla wszystkich standardowych atrybutów: 
th:abbr 
th:accept 
th:accept-charset 
th:accesskey 
th:action 
th:align 
th:alt 
itd.
Ustawianie wartości dowolnych atrybutów 
Thymeleaf umożliwia wstawianie wartości dowolnych np. customowych atrybutów: 
th:attr="attr-name=${object.property}" 
th:attr="src=@{/images/gtvglogo.png}, 
title=#{logo},alt=#{logo}" 
th:attr="data-some-attr=${object.property}"
Dodatkowe wsparcie dla niektórych atrybutów 
Ustawienie kilku atrybutów jednocześnie: 
th:alt-title ustawia alt i title 
Wsparcie dla atrybutów o stałej wartości: 
th:checked 
th:hidden 
th:selected 
th:disabled 
... 
th:checked="${user.active}"
Dodatkowe wsparcie dla niektórych atrybutów 
Wsparcie dla atrybutu class: 
class="row" 
th:classappend="${prodStat.odd} ? 'odd'" 
class="row odd"
Iteracja 
Każda technologia szablonów musi posiadać wsparcie dla wyświetlania kolekcji, map i tablic: 
<tr th:each="prod : ${prods}"> 
<td th:text="${prod.name}">Onions</td> 
<td th:text="${prod.price}">2.41</td> 
</tr>
Iteracja – status 
Możemy zadeklarować zmienną, która będzie przechowywała status iteracji: 
<tr th:each="prod, stat : ${prods}"> 
<td th:text="${stat.count}">1</td> 
<td th:text="${prod.name}">Onions</td> 
<td th:text="${prod.price}">2.41</td> 
</tr> 
Dostępne dane: 
index, count, size, odd, even, last, first
Wsparcie dla prototypowania 
<tr th:each="prod : ${prods}"> 
<td th:text="${prod.name}">Onions</td> 
<td th:text="${prod.price}">2.41</td> 
</tr> 
Jeden wiersz mało atrakcyjny z punktu widzenia prototypu:
Wsparcie dla prototypowania 
<tr th:each="prod : ${prods}"> 
<td th:text="${prod.name}">Onions</td> 
<td th:text="${prod.price}">2.41</td> 
</tr> 
<tr> 
<td>Apples</td> 
<td>3.98</td> 
</tr> 
<tr> 
<td>Oranges</td> 
<td>4.52</td> 
</tr> 
Chcemy, żeby kolejne wiersze były widoczne tylko w prototypie:
Wsparcie dla prototypowania 
<tbody th:remove="all-but-first"> 
<tr th:each="prod : ${prods}"> 
<td th:text="${prod.name}">Onions</td> 
<td th:text="${prod.price}">2.41</td> 
</tr> 
<tr> 
<td>Apples</td> 
<td>3.98</td> 
</tr> 
... 
</tbody> 
Solucja to wykorzystanie th:remove:
Wsparcie dla prototypowania 
all - usuwa tag i wszystkie dzieci 
body - zostawia tag, ale usuwa dzieci 
tag - usuwa tag, ale zostawia dzieci 
all-but-first - usuwa wszystkie dzieci poza pierwszym 
none - przydatne gdy dynamicznie decydujemy o usunięciu elementów i pod pewnym warunkiem chcemy zaniechać usuwania 
Możliwe wartości th:remove:
Czas na kolejne ćwiczenia 
http://itutorial.thymeleaf.org/exercise/6 
http://itutorial.thymeleaf.org/exercise/7 
Ćwiczenia znajdują się pod adresami:
th:if oraz th:unless 
<a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}"> 
view 
</a> 
Warunkowe wyświetlanie tagów: 
<a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}"> 
view 
</a>
th:switch oraz th:case 
<div th:switch="${user.role.name()}"> 
<p th:case="'ADMIN'">User is an administrator</p> 
<p th:case="#{roles.manager}">User is a manager</p> 
<p th:case="*">User is some other thing</p> 
</div> 
Znana z większości języków instrukcja switch:
Czas na kolejne ćwiczenie 
http://itutorial.thymeleaf.org/exercise/8 
Ćwiczenie znajduje się pod adresem:
Zmienne lokalne 
<div th:with="company=${user.company + ' Co.'}> 
... 
</div> 
Czasem może zdarzyć się, że pewne wyrażenie wykorzystujemy wielokrotnie wewnątrz bloku: 
Zalety: 
jednokrotna ewaluacja (być może skomplikowanego) wyrażenia 
nadanie nazwy 
mniej kodu
Fragmenty - definiowanie 
<body> 
… 
<div th:fragment="copy"> 
&copy; 2011 The Good Thymes Virtual Grocery 
</div> 
… 
</body> 
Thymeleaf posiada wsparcie dla wielokrotnego wykorzystania pewnych poddrzew (DRY):
Fragmenty - wykorzystanie 
<div th:include="layout :: copy"></div> 
lub 
<div th:replace="layout :: copy"></div> 
Zdefiniowany w jednym pliku fragment można wykorzystywać w innych plikach:
Fragmenty - czym różnią się th:include i th:replace? 
<footer th:fragment="copy"> &copy; 2011 The Good Thymes Virtual Grocery </footer> <div th:include="layout :: copy"></div> <div th:replace="layout :: copy"></div> <div> &copy; 2011 The Good Thymes Virtual Grocery </div> <footer> &copy; 2011 The Good Thymes Virtual Grocery </footer>
Fragmenty - parametryzowanie 
<div th:fragment="frag (onevar,twovar)"> 
<p th:text="${onevar} + ' - ' + ${twovar}">...</p> 
</div> 
<div th:include="layout::frag(${value1},${value2})"> 
... 
</div> 
Definicja: 
Wykorzystanie:
Wsparcie dla formularzy 
<form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> 
… 
<input type="text" th:field="*{datePlanted}"/> 
… 
</form> 
Atrybut th:object służy do precyzowania form-backing beana: 
th:field zachowuje się odpowiednio w zależności od inputu (inaczej dla text, jeszcze inaczej dla textarea itd.)
Wsparcie dla formularzy 
<li th:each="feat : ${allFeatures}"> 
<input type="checkbox" th:field="*{features}" 
th:value="${feat}"/> 
<label th:for="${#ids.prev('features')}" 
th:text="#{${'feature.' + feat}}">Heating</label> 
</li> 
Checkbox: 
Dropdown: 
<select th:field="*{type}"> 
<option th:each="type : ${allTypes}" 
th:value="${type}" 
th:text="#{${'type.' + type}}">Wireframe</option> 
</select>
Inlining 
<body th:inline="text"> 
... 
<p>Hello, [[${session.user.name}]]!</p> 
... 
</body> 
Mimo, iż możemy osiągnąć wszystko przy pomocy atrybutów, czasem może zdarzyć się, że chcemy wstawić wartość bezpośrednio wewnątrz tagu:
Inlining - JavaScript 
<script th:inline="javascript"> 
var username = /*[[${session.user.name}]]*/ 'Sebastian'; 
</script> 
Thymeleaf posiada wsparcie dla JavaScriptu: 
Thymeleaf jest inteligentny: 
var user = /*[[${session.user}]]*/ null; 
var user = {'firstName':'John', 'lastName':'Apricot', 'name':'John Apricot', 'nationality':'Antarctica'}; 
Wygenerowano literał odpowiedniego typu:
Kolejność przetwarzania atrybutów 
<li th:if="item.status == 'APPROVED'" 
th:each="item : ${items}"> 
</li> 
Atrybuty w dokumentach XML i HTML nie mają określonej kolejności. 
Czasem może zdarzyć się, że kolejność jest dla nas istotna: 
By sobie z tym poradzić, Thymeleaf definiuje kolejność, w jakiej przetwarza atrybuty.
Kolejność przetwarzania atrybutów 
th:include, th:replace 
th:each 
th:if, th:unless, th:switch, th:case 
th:object, th:with 
th:attr, th:attrprepend, th:attrappend 
th:value, th:href, th:src itd. 
th:text, th:utext 
th:fragment 
th:remove
Dostęp do specjalnych obiektów 
#locale 
#vars 
param 
session 
application 
#httpServletRequest 
#httpSession 
Czasem może zdarzyć się, że potrzebny jest nam bezpośredni dostęp do pewnych specjalnych obiektów. 
Najważniejsze z obiektów dostępnych z poziomu szablonu:
Dostęp do Springowych beanów 
Kiedy korzystamy z dialektu Spring Standard, dostajemy pełne możliwości Spring EL. 
Na przykład możemy dostawać się do beanów: 
<div th:text="${@authService.getUserName()}">...</div>
Dialekt Spring Security 
<div sec:authorize="hasRole('ROLE_ADMIN')"> 
This will only be displayed if authenticated 
user has role ROLE_ADMIN. 
</div> 
<a href="#" th:href="@{/admin}" sec:authorize-url="/admin"> 
This will only be displayed if authenticated 
user can call the "/admin" URL. 
</a> 
<div sec:authentication="name"> 
The value of the "name" property of 
the authentication object should appear here. 
</div> 
Możliwości:
http://www.thymeleaf.org/documentation.html 
http://www.thymeleaf.org/doc/springmail.html 
https://github.com/thymeleaf/thymeleaf-testing 
https://github.com/spring-projects/spring- boot/tree/master/spring-boot-samples/spring-boot- sample-web-ui 
Gdzie dalej?
Dziękuję za uwagę!

More Related Content

What's hot

What is Cache and how it works
What is Cache and how it worksWhat is Cache and how it works
What is Cache and how it worksTabraiz Yaseen
 
Cours veille scientifique
Cours veille scientifiqueCours veille scientifique
Cours veille scientifiquepierrepo
 
Chp1 - Introduction à l'Informatique Décisionnelle
Chp1 - Introduction à l'Informatique DécisionnelleChp1 - Introduction à l'Informatique Décisionnelle
Chp1 - Introduction à l'Informatique DécisionnelleLilia Sfaxi
 
Introduction aux bases de données
Introduction aux bases de donnéesIntroduction aux bases de données
Introduction aux bases de donnéesAbdoulaye Dieng
 
AI Apprentissage Automatique, Machine Learnig
AI Apprentissage Automatique, Machine LearnigAI Apprentissage Automatique, Machine Learnig
AI Apprentissage Automatique, Machine LearnigFelipe Sanchez Garzon
 
Chp3 - Modélisation Multidimensionnelle
Chp3 - Modélisation MultidimensionnelleChp3 - Modélisation Multidimensionnelle
Chp3 - Modélisation MultidimensionnelleLilia Sfaxi
 
Exposé de SE Systemes distribués
Exposé de SE Systemes distribuésExposé de SE Systemes distribués
Exposé de SE Systemes distribuésYoussouf Saleh Gao
 
Programmation Shell Script
Programmation Shell ScriptProgrammation Shell Script
Programmation Shell ScriptBoubakr NOUR
 
Operating System Chapter 4
Operating System Chapter 4Operating System Chapter 4
Operating System Chapter 4Nuth Otanasap
 
Chapter 2: Operating System Structures
Chapter 2: Operating System StructuresChapter 2: Operating System Structures
Chapter 2: Operating System StructuresShafaan Khaliq Bhatti
 
Tp1 - OpenERP (1)
Tp1 - OpenERP (1)Tp1 - OpenERP (1)
Tp1 - OpenERP (1)Lilia Sfaxi
 
Chapitre ii architecture interne des processeurs
Chapitre ii architecture interne des processeursChapitre ii architecture interne des processeurs
Chapitre ii architecture interne des processeursSana Aroussi
 
What is a Kernel? : Introduction And Architecture
What is a Kernel? : Introduction And ArchitectureWhat is a Kernel? : Introduction And Architecture
What is a Kernel? : Introduction And Architecturepec2013
 
Cours Big Data Chap3
Cours Big Data Chap3Cours Big Data Chap3
Cours Big Data Chap3Amal Abid
 
Virtualization and Cloud Computing
Virtualization and Cloud ComputingVirtualization and Cloud Computing
Virtualization and Cloud ComputingJosh Folgado
 
Module de formation en foncier et tenue du dossier rural au niger
Module de formation en foncier et tenue du dossier rural au nigerModule de formation en foncier et tenue du dossier rural au niger
Module de formation en foncier et tenue du dossier rural au nigerDjibril Hassane
 

What's hot (20)

What is Cache and how it works
What is Cache and how it worksWhat is Cache and how it works
What is Cache and how it works
 
Cours veille scientifique
Cours veille scientifiqueCours veille scientifique
Cours veille scientifique
 
Chp1 - Introduction à l'Informatique Décisionnelle
Chp1 - Introduction à l'Informatique DécisionnelleChp1 - Introduction à l'Informatique Décisionnelle
Chp1 - Introduction à l'Informatique Décisionnelle
 
Introduction aux bases de données
Introduction aux bases de donnéesIntroduction aux bases de données
Introduction aux bases de données
 
Cache memory
Cache memoryCache memory
Cache memory
 
AI Apprentissage Automatique, Machine Learnig
AI Apprentissage Automatique, Machine LearnigAI Apprentissage Automatique, Machine Learnig
AI Apprentissage Automatique, Machine Learnig
 
Chp3 - Modélisation Multidimensionnelle
Chp3 - Modélisation MultidimensionnelleChp3 - Modélisation Multidimensionnelle
Chp3 - Modélisation Multidimensionnelle
 
Badanie potrzeb użytkowników
Badanie potrzeb użytkownikówBadanie potrzeb użytkowników
Badanie potrzeb użytkowników
 
Exposé de SE Systemes distribués
Exposé de SE Systemes distribuésExposé de SE Systemes distribués
Exposé de SE Systemes distribués
 
Programmation Shell Script
Programmation Shell ScriptProgrammation Shell Script
Programmation Shell Script
 
Operating System Chapter 4
Operating System Chapter 4Operating System Chapter 4
Operating System Chapter 4
 
Ch1-Operating System Concepts
Ch1-Operating System ConceptsCh1-Operating System Concepts
Ch1-Operating System Concepts
 
Chapter 2: Operating System Structures
Chapter 2: Operating System StructuresChapter 2: Operating System Structures
Chapter 2: Operating System Structures
 
MapReduce in Cloud Computing
MapReduce in Cloud ComputingMapReduce in Cloud Computing
MapReduce in Cloud Computing
 
Tp1 - OpenERP (1)
Tp1 - OpenERP (1)Tp1 - OpenERP (1)
Tp1 - OpenERP (1)
 
Chapitre ii architecture interne des processeurs
Chapitre ii architecture interne des processeursChapitre ii architecture interne des processeurs
Chapitre ii architecture interne des processeurs
 
What is a Kernel? : Introduction And Architecture
What is a Kernel? : Introduction And ArchitectureWhat is a Kernel? : Introduction And Architecture
What is a Kernel? : Introduction And Architecture
 
Cours Big Data Chap3
Cours Big Data Chap3Cours Big Data Chap3
Cours Big Data Chap3
 
Virtualization and Cloud Computing
Virtualization and Cloud ComputingVirtualization and Cloud Computing
Virtualization and Cloud Computing
 
Module de formation en foncier et tenue du dossier rural au niger
Module de formation en foncier et tenue du dossier rural au nigerModule de formation en foncier et tenue du dossier rural au niger
Module de formation en foncier et tenue du dossier rural au niger
 

Similar to Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka

TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPPiotr Gabryjeluk
 
Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaWojciech Lichota
 
ASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaBartlomiej Zass
 
NK API - Przykłady
NK API - PrzykładyNK API - Przykłady
NK API - Przykładynasza-klasa
 
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?PHPCon Poland
 
Optymalizacja aplikacji ASP.NET
Optymalizacja aplikacji ASP.NETOptymalizacja aplikacji ASP.NET
Optymalizacja aplikacji ASP.NETBartlomiej Zass
 
Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Maciek Próchniak
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?The Software House
 
HTML5 - now or later
HTML5 - now or laterHTML5 - now or later
HTML5 - now or laterKasia Drzyzga
 
Jarorcon Sp
Jarorcon SpJarorcon Sp
Jarorcon Spjarorcon
 
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...Tomasz Kopacz
 
Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztatyintive
 
Budowa elementów GUI za pomocą biblioteki React - szybki start
Budowa elementów GUI za pomocą biblioteki React - szybki startBudowa elementów GUI za pomocą biblioteki React - szybki start
Budowa elementów GUI za pomocą biblioteki React - szybki startSages
 
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationMariusz Koprowski
 
tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?Brainhub
 
Zwiększanie produktywności programisty php (v2)
Zwiększanie produktywności programisty php (v2)Zwiększanie produktywności programisty php (v2)
Zwiększanie produktywności programisty php (v2)adamhmetal
 
Zwiększanie produktywności programisty php
Zwiększanie produktywności programisty phpZwiększanie produktywności programisty php
Zwiększanie produktywności programisty phpadamhmetal
 

Similar to Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka (20)

TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHP
 
react-pl.pdf
react-pl.pdfreact-pl.pdf
react-pl.pdf
 
Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użycia
 
ASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założeniaASP.NET MVC - najważniejsze założenia
ASP.NET MVC - najważniejsze założenia
 
NK API - Przykłady
NK API - PrzykładyNK API - Przykłady
NK API - Przykłady
 
Silverlight i PHP
Silverlight i PHPSilverlight i PHP
Silverlight i PHP
 
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?
Silverlight i PHP - jak budować interfejs nowoczesnych aplikacji internetowych?
 
Optymalizacja aplikacji ASP.NET
Optymalizacja aplikacji ASP.NETOptymalizacja aplikacji ASP.NET
Optymalizacja aplikacji ASP.NET
 
Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010
 
Android i REST
Android i RESTAndroid i REST
Android i REST
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
 
HTML5 - now or later
HTML5 - now or laterHTML5 - now or later
HTML5 - now or later
 
Jarorcon Sp
Jarorcon SpJarorcon Sp
Jarorcon Sp
 
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
 
Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztaty
 
Budowa elementów GUI za pomocą biblioteki React - szybki start
Budowa elementów GUI za pomocą biblioteki React - szybki startBudowa elementów GUI za pomocą biblioteki React - szybki start
Budowa elementów GUI za pomocą biblioteki React - szybki start
 
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentation
 
tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?
 
Zwiększanie produktywności programisty php (v2)
Zwiększanie produktywności programisty php (v2)Zwiększanie produktywności programisty php (v2)
Zwiększanie produktywności programisty php (v2)
 
Zwiększanie produktywności programisty php
Zwiększanie produktywności programisty phpZwiększanie produktywności programisty php
Zwiększanie produktywności programisty php
 

Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka

  • 1. Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka Maciej Ziarko 14.10.2014
  • 2. Dowiecie się, czym jest i co potrafi Thymeleaf Wykonacie kilka ćwiczeń w webowym tutorialu Będziecie mogli jutro z marszu wykorzystać Thymeleaf we własnym projekcie Dowiecie się, gdzie poszerzyć swoją wiedzę, gdy zajdzie taka potrzeba Cel dzisiejszego spotkania?
  • 3. Potężny silnik szablonów, potrafiący generować dokumenty XML/XHTML/HTML5 Szablony są poprawnymi dokumentami XML/XHTML/HTML5 Wiele dialektów (możliwość tworzenia własnych) Twórcy biblioteki zapewniają integrację ze Spring MVC i Spring Security Wysoka wydajność dzięki mechanizmowy pamięci podręcznej Czym jest Thymeleaf?
  • 5. Jak to wygląda w Spring MVC? @RequestMapping("/somePage") String showSomePage(Model model) { model.addAttribute("key1", new Value1()) model.addAttribute("key2", new Value2()) return "templateName" } Dzięki integracji ze Spring MVC i auto-konfiguracji w Spring Boot proces z poprzedniego slajdu może być zupełnie transparentny dla programisty
  • 6. Przykład prostego szablonu <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <body> <p th:text="#{wjug.welcome}"> Welcome to WJUG! </p> </body> </html>
  • 7. Informacje potrzebne bibliotece przekazywane są przy pomocy atrybutów, a nie tagów Czołowe przeglądarki ignorują nieznane przez siebie atrybuty Natural Templating – szablony, które mogą być jednocześnie prototypem, który można uruchomić w przeglądarce bez przetwarzania Zupełnie inaczej jest w przypadku większości popularnych dawniej technologii szablonowych: JSP, Freemarker, Velocity itd. Analiza prostego szablonu
  • 8. Thymeleaf jest bardzo elastyczny – rozszerzalny przy pomocy nowych dialektów Silnik szablonów może korzystać jednocześnie z wielu dialektów Głównym składnikiem dialektu są procesory, które wiedzą, jak interpretować poszczególne atrybuty Można tworzyć nowe dialekty w oparciu o istniejące Najpopularniejsze dialekty: Standard, Spring Standard, Spring Security, Layout Dialekty
  • 9. th:text <p th:text="#{wjug.welcome}"> Welcome to WJUG! </p> Wylicza wartość wyrażenia i zastępuje nią wnętrze tagu Wyliczona wartość może być bezpiecznie umieszczona w dokumencie HTML (escaping) wjug.welcome=Witamy na WJUG! W pliku messages_pl.properties:
  • 10. th:utext <p th:utext="#{wjug.welcome}"> Welcome to <strong>WJUG</strong>! </p> Czasem może zdarzyć się, że z jakiegoś powodu escaping nie jest pożądany wjug.welcome=Witamy na <strong>WJUG</strong>! W pliku messages_pl.properties:
  • 11. Składnia wyrażeń - ${…} <span th:text="${user.name}"> j_kowalski </span> ${…} oblicza wartość na podstawie zmiennych znajdujących się w kontekście
  • 12. Dostęp do elementów mapy, pól obiektów… map['key'] map.key Wyciąganie elementów mapy: Wyciąganie pól z obiektów: object['field'] object.field Wołanie metod: person.countDebt() Elementy listy/tablicy: people[2]
  • 13. Składnia wyrażeń - #{…} <p th:text="#{wjug.welcome(${user.name})}"> Welcome to WJUG, Johnny Kowalski! </p> #{…} jest wykorzystywane do internacjonalizacji – wartość jest ustalana na postawie Locale oraz plików properties wjug.welcome=Witamy na WJUG, {0}! W pliku messages_pl.properties:
  • 14. Składnia wyrażeń - @{…} @{…} jest wykorzystywane do tworzenia odnośników Szczególnie przydatne dla th:href W przypadku web aplikacji dodaje do odnośnika ścieżkę kontekstową Umożliwia ustawianie parametrów
  • 15. Dla aplikacji ze ścieżką kontekstową /app zostanie zmienione na: @{…} – ścieżka kontekstowa <a href="profile.html" th:href="@{/profile}"> profile </a> <a href="/app/profile"> profile </a>
  • 16. @{…} - parametry <a href="details.html" th:href="@{/order/details(orderId=${o.id})}"> view </a> Dla o.id równego 100 zostanie zamienione na: <a href="/app/order/details?orderId=100"> view </a>
  • 17. @{…} - parametry @{/order/process(execId=${execId},execType='FAST')} Można ustawić kilka parametrów na raz: A także parametryzować zmienne wewnątrz ścieżki: @{/order/{orderId}/details(orderId=${o.id})}
  • 18. Konkatenacja łańcuchów znaków th:text="'The name of the user is ' + ${user.name}" Łańcuchy znaków można konkatenować korzystając z operatora +: Można też skorzystać ze specjalnej składni literal substitutions: th:text="|Welcome to our application, ${user.name}!|"
  • 19. Czas na pierwsze ćwiczenie http://itutorial.thymeleaf.org/exercise/1 Ćwiczenie znajduje się pod adresem:
  • 20. th:object i *{…} th:text="${product.description}" th:text="${product.price}" Atrybut th:object oraz *{…} pozwalają ulepszyć nasz kod: Jako dobrzy inżynierowie nie lubimy duplikacji: <dl th:object="${product}"> <dt>Product name</dt> <dd th:text="*{description}">...</dd> </dl>
  • 21. Rozwiążmy lepiej ćwiczenie pierwsze http://itutorial.thymeleaf.org/exercise/1 Ćwiczenie znajduje się pod adresem:
  • 22. Utility Objects #dates #calendars #numbers Obiekty, posiadające pomocnicze metody: Głównie przydają się do różnego rodzaju formatowania: ${#numbers.formatInteger(num,3)} ${#numbers.formatDecimal(num,3,2)} ${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
  • 23. Czas na drugie ćwiczenie http://itutorial.thymeleaf.org/exercise/2 Ćwiczenie znajduje się pod adresem:
  • 24. Ustawianie wartości atrybutów Thymeleaf umożliwia wstawianie wartości dla wszystkich standardowych atrybutów: th:abbr th:accept th:accept-charset th:accesskey th:action th:align th:alt itd.
  • 25. Ustawianie wartości dowolnych atrybutów Thymeleaf umożliwia wstawianie wartości dowolnych np. customowych atrybutów: th:attr="attr-name=${object.property}" th:attr="src=@{/images/gtvglogo.png}, title=#{logo},alt=#{logo}" th:attr="data-some-attr=${object.property}"
  • 26. Dodatkowe wsparcie dla niektórych atrybutów Ustawienie kilku atrybutów jednocześnie: th:alt-title ustawia alt i title Wsparcie dla atrybutów o stałej wartości: th:checked th:hidden th:selected th:disabled ... th:checked="${user.active}"
  • 27. Dodatkowe wsparcie dla niektórych atrybutów Wsparcie dla atrybutu class: class="row" th:classappend="${prodStat.odd} ? 'odd'" class="row odd"
  • 28. Iteracja Każda technologia szablonów musi posiadać wsparcie dla wyświetlania kolekcji, map i tablic: <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> </tr>
  • 29. Iteracja – status Możemy zadeklarować zmienną, która będzie przechowywała status iteracji: <tr th:each="prod, stat : ${prods}"> <td th:text="${stat.count}">1</td> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> </tr> Dostępne dane: index, count, size, odd, even, last, first
  • 30. Wsparcie dla prototypowania <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> </tr> Jeden wiersz mało atrakcyjny z punktu widzenia prototypu:
  • 31. Wsparcie dla prototypowania <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> </tr> <tr> <td>Apples</td> <td>3.98</td> </tr> <tr> <td>Oranges</td> <td>4.52</td> </tr> Chcemy, żeby kolejne wiersze były widoczne tylko w prototypie:
  • 32. Wsparcie dla prototypowania <tbody th:remove="all-but-first"> <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> </tr> <tr> <td>Apples</td> <td>3.98</td> </tr> ... </tbody> Solucja to wykorzystanie th:remove:
  • 33. Wsparcie dla prototypowania all - usuwa tag i wszystkie dzieci body - zostawia tag, ale usuwa dzieci tag - usuwa tag, ale zostawia dzieci all-but-first - usuwa wszystkie dzieci poza pierwszym none - przydatne gdy dynamicznie decydujemy o usunięciu elementów i pod pewnym warunkiem chcemy zaniechać usuwania Możliwe wartości th:remove:
  • 34. Czas na kolejne ćwiczenia http://itutorial.thymeleaf.org/exercise/6 http://itutorial.thymeleaf.org/exercise/7 Ćwiczenia znajdują się pod adresami:
  • 35. th:if oraz th:unless <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}"> view </a> Warunkowe wyświetlanie tagów: <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}"> view </a>
  • 36. th:switch oraz th:case <div th:switch="${user.role.name()}"> <p th:case="'ADMIN'">User is an administrator</p> <p th:case="#{roles.manager}">User is a manager</p> <p th:case="*">User is some other thing</p> </div> Znana z większości języków instrukcja switch:
  • 37. Czas na kolejne ćwiczenie http://itutorial.thymeleaf.org/exercise/8 Ćwiczenie znajduje się pod adresem:
  • 38. Zmienne lokalne <div th:with="company=${user.company + ' Co.'}> ... </div> Czasem może zdarzyć się, że pewne wyrażenie wykorzystujemy wielokrotnie wewnątrz bloku: Zalety: jednokrotna ewaluacja (być może skomplikowanego) wyrażenia nadanie nazwy mniej kodu
  • 39. Fragmenty - definiowanie <body> … <div th:fragment="copy"> &copy; 2011 The Good Thymes Virtual Grocery </div> … </body> Thymeleaf posiada wsparcie dla wielokrotnego wykorzystania pewnych poddrzew (DRY):
  • 40. Fragmenty - wykorzystanie <div th:include="layout :: copy"></div> lub <div th:replace="layout :: copy"></div> Zdefiniowany w jednym pliku fragment można wykorzystywać w innych plikach:
  • 41. Fragmenty - czym różnią się th:include i th:replace? <footer th:fragment="copy"> &copy; 2011 The Good Thymes Virtual Grocery </footer> <div th:include="layout :: copy"></div> <div th:replace="layout :: copy"></div> <div> &copy; 2011 The Good Thymes Virtual Grocery </div> <footer> &copy; 2011 The Good Thymes Virtual Grocery </footer>
  • 42. Fragmenty - parametryzowanie <div th:fragment="frag (onevar,twovar)"> <p th:text="${onevar} + ' - ' + ${twovar}">...</p> </div> <div th:include="layout::frag(${value1},${value2})"> ... </div> Definicja: Wykorzystanie:
  • 43. Wsparcie dla formularzy <form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post"> … <input type="text" th:field="*{datePlanted}"/> … </form> Atrybut th:object służy do precyzowania form-backing beana: th:field zachowuje się odpowiednio w zależności od inputu (inaczej dla text, jeszcze inaczej dla textarea itd.)
  • 44. Wsparcie dla formularzy <li th:each="feat : ${allFeatures}"> <input type="checkbox" th:field="*{features}" th:value="${feat}"/> <label th:for="${#ids.prev('features')}" th:text="#{${'feature.' + feat}}">Heating</label> </li> Checkbox: Dropdown: <select th:field="*{type}"> <option th:each="type : ${allTypes}" th:value="${type}" th:text="#{${'type.' + type}}">Wireframe</option> </select>
  • 45. Inlining <body th:inline="text"> ... <p>Hello, [[${session.user.name}]]!</p> ... </body> Mimo, iż możemy osiągnąć wszystko przy pomocy atrybutów, czasem może zdarzyć się, że chcemy wstawić wartość bezpośrednio wewnątrz tagu:
  • 46. Inlining - JavaScript <script th:inline="javascript"> var username = /*[[${session.user.name}]]*/ 'Sebastian'; </script> Thymeleaf posiada wsparcie dla JavaScriptu: Thymeleaf jest inteligentny: var user = /*[[${session.user}]]*/ null; var user = {'firstName':'John', 'lastName':'Apricot', 'name':'John Apricot', 'nationality':'Antarctica'}; Wygenerowano literał odpowiedniego typu:
  • 47. Kolejność przetwarzania atrybutów <li th:if="item.status == 'APPROVED'" th:each="item : ${items}"> </li> Atrybuty w dokumentach XML i HTML nie mają określonej kolejności. Czasem może zdarzyć się, że kolejność jest dla nas istotna: By sobie z tym poradzić, Thymeleaf definiuje kolejność, w jakiej przetwarza atrybuty.
  • 48. Kolejność przetwarzania atrybutów th:include, th:replace th:each th:if, th:unless, th:switch, th:case th:object, th:with th:attr, th:attrprepend, th:attrappend th:value, th:href, th:src itd. th:text, th:utext th:fragment th:remove
  • 49. Dostęp do specjalnych obiektów #locale #vars param session application #httpServletRequest #httpSession Czasem może zdarzyć się, że potrzebny jest nam bezpośredni dostęp do pewnych specjalnych obiektów. Najważniejsze z obiektów dostępnych z poziomu szablonu:
  • 50. Dostęp do Springowych beanów Kiedy korzystamy z dialektu Spring Standard, dostajemy pełne możliwości Spring EL. Na przykład możemy dostawać się do beanów: <div th:text="${@authService.getUserName()}">...</div>
  • 51. Dialekt Spring Security <div sec:authorize="hasRole('ROLE_ADMIN')"> This will only be displayed if authenticated user has role ROLE_ADMIN. </div> <a href="#" th:href="@{/admin}" sec:authorize-url="/admin"> This will only be displayed if authenticated user can call the "/admin" URL. </a> <div sec:authentication="name"> The value of the "name" property of the authentication object should appear here. </div> Możliwości:
  • 52. http://www.thymeleaf.org/documentation.html http://www.thymeleaf.org/doc/springmail.html https://github.com/thymeleaf/thymeleaf-testing https://github.com/spring-projects/spring- boot/tree/master/spring-boot-samples/spring-boot- sample-web-ui Gdzie dalej?