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 Php
What Is PhpWhat Is Php
What Is PhpAVC
 
History of Web Technology
History of Web TechnologyHistory of Web Technology
History of Web TechnologyShuvo Malakar
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutesSimon Willison
 
Hexagonal architecture with Spring Boot [EPAM Java online conference]
Hexagonal architecture with Spring Boot [EPAM Java online conference]Hexagonal architecture with Spring Boot [EPAM Java online conference]
Hexagonal architecture with Spring Boot [EPAM Java online conference]Mikalai Alimenkou
 
Introduction to Drupal Basics
Introduction to Drupal BasicsIntroduction to Drupal Basics
Introduction to Drupal BasicsJuha Niemi
 
Startup Metrics For Scottish Pirates (AARRR!) v1.3
Startup Metrics For Scottish Pirates (AARRR!) v1.3Startup Metrics For Scottish Pirates (AARRR!) v1.3
Startup Metrics For Scottish Pirates (AARRR!) v1.3Dave McClure
 
Oracle forms les25
Oracle forms  les25Oracle forms  les25
Oracle forms les25Abed Othman
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in phpCPD INDIA
 
Rest and Sling Resolution
Rest and Sling ResolutionRest and Sling Resolution
Rest and Sling ResolutionDEEPAK KHETAWAT
 
Different Types of Web Hosting Services
Different Types of Web Hosting ServicesDifferent Types of Web Hosting Services
Different Types of Web Hosting ServicesJude Pugh
 
Php (myanmar)
Php (myanmar) Php (myanmar)
Php (myanmar) nayhlaing
 
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...Edureka!
 

What's hot (20)

What Is Php
What Is PhpWhat Is Php
What Is Php
 
History of Web Technology
History of Web TechnologyHistory of Web Technology
History of Web Technology
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutes
 
Jquery
JqueryJquery
Jquery
 
Hexagonal architecture with Spring Boot [EPAM Java online conference]
Hexagonal architecture with Spring Boot [EPAM Java online conference]Hexagonal architecture with Spring Boot [EPAM Java online conference]
Hexagonal architecture with Spring Boot [EPAM Java online conference]
 
Content Management System
Content Management SystemContent Management System
Content Management System
 
Introduction to Drupal Basics
Introduction to Drupal BasicsIntroduction to Drupal Basics
Introduction to Drupal Basics
 
Joomla
JoomlaJoomla
Joomla
 
Introduction to HTML and CSS
Introduction to HTML and CSSIntroduction to HTML and CSS
Introduction to HTML and CSS
 
Up to Speed on HTML 5 and CSS 3
Up to Speed on HTML 5 and CSS 3Up to Speed on HTML 5 and CSS 3
Up to Speed on HTML 5 and CSS 3
 
Startup Metrics For Scottish Pirates (AARRR!) v1.3
Startup Metrics For Scottish Pirates (AARRR!) v1.3Startup Metrics For Scottish Pirates (AARRR!) v1.3
Startup Metrics For Scottish Pirates (AARRR!) v1.3
 
Php mysql ppt
Php mysql pptPhp mysql ppt
Php mysql ppt
 
Oracle forms les25
Oracle forms  les25Oracle forms  les25
Oracle forms les25
 
Oops concepts in php
Oops concepts in phpOops concepts in php
Oops concepts in php
 
Rest and Sling Resolution
Rest and Sling ResolutionRest and Sling Resolution
Rest and Sling Resolution
 
WEB HOSTING
WEB HOSTINGWEB HOSTING
WEB HOSTING
 
Different Types of Web Hosting Services
Different Types of Web Hosting ServicesDifferent Types of Web Hosting Services
Different Types of Web Hosting Services
 
Alyce
AlyceAlyce
Alyce
 
Php (myanmar)
Php (myanmar) Php (myanmar)
Php (myanmar)
 
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...
Spring Boot Tutorial | Microservices Spring Boot | Microservices Architecture...
 

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
Zwiększanie produktywności programisty phpZwiększanie produktywności programisty php
Zwiększanie produktywności programisty phpadamhmetal
 
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
 

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 - 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?
 
Silverlight i PHP
Silverlight i PHPSilverlight i PHP
Silverlight i PHP
 
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
Zwiększanie produktywności programisty phpZwiększanie produktywności programisty php
Zwiększanie produktywności programisty php
 
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)
 

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?