53
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka Maciej Ziarko 14.10.2014

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

Embed Size (px)

DESCRIPTION

WJUG presentation about Thymeleaf. Language: polish

Citation preview

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

Thymeleaf - szablony, które bez przetworzenia zrozumie twoja

przeglądarka

Maciej Ziarko

14.10.2014

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

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?

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

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?

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

Jak działa Thymeleaf?

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

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

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

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>

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

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

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

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

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

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:

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

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:

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

Składnia wyrażeń - ${…}

<span th:text="${user.name}">

j_kowalski

</span>

${…} oblicza wartość na podstawie zmiennych znajdujących się w kontekście

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

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]

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

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:

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

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

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

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>

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

@{…} - 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>

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

@{…} - 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})}

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

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}!|"

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

Czas na pierwsze ćwiczenie

http://itutorial.thymeleaf.org/exercise/1

Ćwiczenie znajduje się pod adresem:

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

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>

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

Rozwiążmy lepiej ćwiczenie pierwsze

http://itutorial.thymeleaf.org/exercise/1

Ćwiczenie znajduje się pod adresem:

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

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')}

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

Czas na drugie ćwiczenie

http://itutorial.thymeleaf.org/exercise/2

Ćwiczenie znajduje się pod adresem:

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

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.

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

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}"

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

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}"

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

Dodatkowe wsparcie dla niektórych atrybutów

Wsparcie dla atrybutu class:

class="row"

th:classappend="${prodStat.odd} ? 'odd'"

class="row odd"

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

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>

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

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

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

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:

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

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:

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

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:

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

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:

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

Czas na kolejne ćwiczenia

http://itutorial.thymeleaf.org/exercise/6

http://itutorial.thymeleaf.org/exercise/7

Ćwiczenia znajdują się pod adresami:

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

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>

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

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:

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

Czas na kolejne ćwiczenie

http://itutorial.thymeleaf.org/exercise/8

Ćwiczenie znajduje się pod adresem:

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

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

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

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):

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

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:

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

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>

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

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:

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

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.)

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

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>

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

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:

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

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:

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

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.

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

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

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

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:

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

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>

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

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:

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

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?

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

Dziękuję za uwagę!