Оглавление
В этой главе мы объясним, как можем установить (или изменить) значения атрибутов в разметке.
Скажем, наш сайт публикует информационный бюллетень, и мы хотим, чтобы пользователи могли подписаться на него, поэтому создаем шаблон /WEB-INF/templates/subscribe.html с формой:
Как и в случае с Thymeleaf, этот шаблон начинается, скорее, как статический прототип, чем шаблон для веб-приложения. Во-первых, атрибут действия в нашей форме статически связывается с самим файлом шаблона, так что нет места для полезной перезаписи URL. Во-вторых, атрибут value в кнопке submit позволяет отображать текст на английском языке, но мы хотели бы, чтобы он был интернационализирован.
Тогда используем атрибут th:attr, способный изменять значение атрибутов тегов, в которых он установлен:
Концепция довольно проста: th:attr принимает выражение, которое выполняет и присваивает атрибуту полученное значение. Создав соответствующие файлы контроллеров и сообщений, результатом обработки файла будет:
Помимо новых значений атрибутов вы также можете увидеть, что имя контекста приложения автоматически было добавлено в базу URL в /gtvg/subscribe, как описано в предыдущей главе.
Но что, если бы мы хотели установить более одного атрибута за раз? XML-правила не позволяют вам устанавливать атрибут дважды в теге, поэтому th:attr возьмет список назначений, разделенных запятыми, например:
Учитывая необходимые файлы сообщений, это будет выводить:
К настоящему моменту вы могли бы подумать, что что-то вроде:
… довольно некрасивый кусок разметки. Указание назначения внутри значения атрибута может быть очень практичным, но это не самый элегантный способ создания шаблонов, если вы должны делать это все время.
Thymeleaf соглашается с вами, и именно поэтому th:attr вряд ли используется в шаблонах. Обычно вы будете использовать другие атрибуты th:*, задача которых заключается в настройке определенных атрибутов тега (а не только любого атрибута, такого как th:attr).
Например, чтобы установить атрибут value, используйте значение th:value:
Это выглядит намного лучше! Давайте попробуем сделать то же самое с атрибутом action в теге form:
И помните ли вы эти th:href, которые мы помещали в наш home.html раньше? Это точно такие же атрибуты:
Таких атрибутов достаточно много, каждый из которых нацелен на определенный атрибут HTML5:
Есть два довольно специальных атрибута, называемых th:alt-title и th:lang-xmllang, которые могут использоваться для одновременного задания двух атрибутов в одно и то же время. В частности:
th:alt-title будет задано значение alt и title.
th:lang-xmllang будет устанавливать lang и xml:lang
Для нашей домашней страницы GTVG это позволит нам заменить это:
… или это, что эквивалентно:
… на это:
Thymeleaf также предлагает атрибуты th:attrappend и th:attrprepend, которые добавляют (суффикс) или добавляют (префикс) результат к существующим значениям атрибутов.
Например, вы можете захотеть сохранить имя добавляемого класса CSS для одной из ваших кнопок в переменной контекста, поскольку конкретный класс CSS, который будет использоваться, будет зависеть от того, что пользователь сделал до того:
Если вы обрабатываете этот шаблон с переменной cssStyle, установленной в «warning», вы получите:
В Standard Dialect есть также два специальных атрибута добавления: атрибуты th:classappend и th:styleappend, которые используются для добавления класса CSS или фрагмента стиля к элементу без перезаписывания существующих:
(Не беспокойтесь о значении th:each. Это атрибут итерации, и мы поговорим об этом позже).
HTML имеет концепцию логических атрибутов, которые активируются только, если их значение «true». В XHTML эти атрибуты принимают только одно значение, которым и являются.
Например, проверьте:
Standard Dialect включает в себя атрибуты, которые позволяют вам устанавливать эти атрибуты по условию, так что если его значение равно «true», атрибут будет установлен в его фиксированное значение, а если он будет равен «false», атрибут не будет установлен:
В Standard Dialect существуют следующие логические атрибуты с фиксированным значением:
Thymeleaf предлагает процессор атрибутов по умолчанию, который позволяет нам устанавливать значение любого атрибута, даже если для него не определен th:* конкретный процессор в Standard Dialect.
Что-то вроде этого:
Результатом будет:
Также можно использовать совершенно другой синтаксис для применения процессоров к вашим шаблонам более удобным для HTML5 способом.
Синтаксис data-{prefix}-{name} является стандартным способом записи пользовательских атрибутов в HTML5, не требуя от разработчиков использования namespaced, таких как th:*. Thymeleaf делает этот синтаксис автоматически доступным для всех ваших диалектов (не только для Standard).
Существует также синтаксис для указания пользовательских тегов: {prefix}-{name}, который следует спецификации W3C Custom Elements (часть большой спецификации W3C Web Components). Это можно использовать, например, для элемента th:block (или th-block), который будет объяснен в следующем разделе.
Важно: этот синтаксис является дополнением к namespaced th:*, он не заменяет его. Нет никакого намерения вообще отказаться от namespaced синтаксиса в будущем.
5 Установка значений атрибутов
В этой главе мы объясним, как можем установить (или изменить) значения атрибутов в разметке.
5.1 Установка значения любого атрибута
Скажем, наш сайт публикует информационный бюллетень, и мы хотим, чтобы пользователи могли подписаться на него, поэтому создаем шаблон /WEB-INF/templates/subscribe.html с формой:
<form action="subscribe.html">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe!" />
</fieldset>
</form>
Как и в случае с Thymeleaf, этот шаблон начинается, скорее, как статический прототип, чем шаблон для веб-приложения. Во-первых, атрибут действия в нашей форме статически связывается с самим файлом шаблона, так что нет места для полезной перезаписи URL. Во-вторых, атрибут value в кнопке submit позволяет отображать текст на английском языке, но мы хотели бы, чтобы он был интернационализирован.
Тогда используем атрибут th:attr, способный изменять значение атрибутов тегов, в которых он установлен:
<form action="subscribe.html" th:attr="action=@{/subscribe}">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
</fieldset>
</form>
Концепция довольно проста: th:attr принимает выражение, которое выполняет и присваивает атрибуту полученное значение. Создав соответствующие файлы контроллеров и сообщений, результатом обработки файла будет:
<form action="/gtvg/subscribe">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="?Suscribe!"/>
</fieldset>
</form>
Помимо новых значений атрибутов вы также можете увидеть, что имя контекста приложения автоматически было добавлено в базу URL в /gtvg/subscribe, как описано в предыдущей главе.
Но что, если бы мы хотели установить более одного атрибута за раз? XML-правила не позволяют вам устанавливать атрибут дважды в теге, поэтому th:attr возьмет список назначений, разделенных запятыми, например:
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
Учитывая необходимые файлы сообщений, это будет выводить:
<img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />
5.2 Установка значения для определенных атрибутов
К настоящему моменту вы могли бы подумать, что что-то вроде:
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
… довольно некрасивый кусок разметки. Указание назначения внутри значения атрибута может быть очень практичным, но это не самый элегантный способ создания шаблонов, если вы должны делать это все время.
Thymeleaf соглашается с вами, и именно поэтому th:attr вряд ли используется в шаблонах. Обычно вы будете использовать другие атрибуты th:*, задача которых заключается в настройке определенных атрибутов тега (а не только любого атрибута, такого как th:attr).
Например, чтобы установить атрибут value, используйте значение th:value:
<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>
Это выглядит намного лучше! Давайте попробуем сделать то же самое с атрибутом action в теге form:
<form action="subscribe.html" th:action="@{/subscribe}">
И помните ли вы эти th:href, которые мы помещали в наш home.html раньше? Это точно такие же атрибуты:
<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>
Таких атрибутов достаточно много, каждый из которых нацелен на определенный атрибут HTML5:
th:abbr |
th:accept |
th:accept-charset |
th:accesskey |
th:action |
th:align |
th:alt |
th:archive |
th:audio |
th:autocomplete |
th:axis |
th:background |
th:bgcolor |
th:border |
th:cellpadding |
th:cellspacing |
th:challenge |
th:charset |
th:cite |
th:class |
th:classid |
th:codebase |
th:codetype |
th:cols |
th:colspan |
th:compact |
th:content |
th:contenteditable |
th:contextmenu |
th:data |
th:datetime |
th:dir |
th:draggable |
th:dropzone |
th:enctype |
th:for |
th:form |
th:formaction |
th:formenctype |
th:formmethod |
th:formtarget |
th:fragment |
th:frame |
th:frameborder |
th:headers |
th:height |
th:high |
th:href |
th:hreflang |
th:hspace |
th:http-equiv |
th:icon |
th:id |
th:inline |
th:keytype |
th:kind |
th:label |
th:lang |
th:list |
th:longdesc |
th:low |
th:manifest |
th:marginheight |
th:marginwidth |
th:max |
th:maxlength |
th:media |
th:method |
th:min |
th:name |
th:onabort |
th:onafterprint |
th:onbeforeprint |
th:onbeforeunload |
th:onblur |
th:oncanplay |
th:oncanplaythrough |
th:onchange |
th:onclick |
th:oncontextmenu |
th:ondblclick |
th:ondrag |
th:ondragend |
th:ondragenter |
th:ondragleave |
th:ondragover |
th:ondragstart |
th:ondrop |
th:ondurationchange |
th:onemptied |
th:onended |
th:onerror |
th:onfocus |
th:onformchange |
th:onforminput |
th:onhashchange |
th:oninput |
th:oninvalid |
th:onkeydown |
th:onkeypress |
th:onkeyup |
th:onload |
th:onloadeddata |
th:onloadedmetadata |
th:onloadstart |
th:onmessage |
th:onmousedown |
th:onmousemove |
th:onmouseout |
th:onmouseover |
th:onmouseup |
th:onmousewheel |
th:onoffline |
th:ononline |
th:onpause |
th:onplay |
th:onplaying |
th:onpopstate |
th:onprogress |
th:onratechange |
th:onreadystatechange |
th:onredo |
th:onreset |
th:onresize |
th:onscroll |
th:onseeked |
th:onseeking |
th:onselect |
th:onshow |
th:onstalled |
th:onstorage |
th:onsubmit |
th:onsuspend |
th:ontimeupdate |
th:onundo |
th:onunload |
th:onvolumechange |
th:onwaiting |
th:optimum |
th:pattern |
th:placeholder |
th:poster |
th:preload |
th:radiogroup |
th:rel |
th:rev |
th:rows |
th:rowspan |
th:rules |
th:sandbox |
th:scheme |
th:scope |
th:scrolling |
th:size |
th:sizes |
th:span |
th:spellcheck |
th:src |
th:srclang |
th:standby |
th:start |
th:step |
th:style |
th:summary |
th:tabindex |
th:target |
th:title |
th:type |
th:usemap |
th:value |
th:valuetype |
th:vspace |
th:width |
th:wrap |
th:xmlbase |
th:xmllang |
th:xmlspace |
5.3 Установка нескольких значений за раз
Есть два довольно специальных атрибута, называемых th:alt-title и th:lang-xmllang, которые могут использоваться для одновременного задания двух атрибутов в одно и то же время. В частности:
th:alt-title будет задано значение alt и title.
th:lang-xmllang будет устанавливать lang и xml:lang
Для нашей домашней страницы GTVG это позволит нам заменить это:
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
… или это, что эквивалентно:
<img src="../../images/gtvglogo.png"
th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />
… на это:
<img src="../../images/gtvglogo.png"
th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" />
5.4 Добавить до- и -после
Thymeleaf также предлагает атрибуты th:attrappend и th:attrprepend, которые добавляют (суффикс) или добавляют (префикс) результат к существующим значениям атрибутов.
Например, вы можете захотеть сохранить имя добавляемого класса CSS для одной из ваших кнопок в переменной контекста, поскольку конкретный класс CSS, который будет использоваться, будет зависеть от того, что пользователь сделал до того:
<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />
Если вы обрабатываете этот шаблон с переменной cssStyle, установленной в «warning», вы получите:
<input type="button" value="Do it!" class="btn warning" />
В Standard Dialect есть также два специальных атрибута добавления: атрибуты th:classappend и th:styleappend, которые используются для добавления класса CSS или фрагмента стиля к элементу без перезаписывания существующих:
<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
(Не беспокойтесь о значении th:each. Это атрибут итерации, и мы поговорим об этом позже).
5.5 Булевые аттрибуты с фиксированным значением
HTML имеет концепцию логических атрибутов, которые активируются только, если их значение «true». В XHTML эти атрибуты принимают только одно значение, которым и являются.
Например, проверьте:
<input type="checkbox" name="option2" checked /> <!-- HTML -->
<input type="checkbox" name="option1" checked="checked" /> <!-- XHTML -->
Standard Dialect включает в себя атрибуты, которые позволяют вам устанавливать эти атрибуты по условию, так что если его значение равно «true», атрибут будет установлен в его фиксированное значение, а если он будет равен «false», атрибут не будет установлен:
<input type="checkbox" name="active" th:checked="${user.active}" />
В Standard Dialect существуют следующие логические атрибуты с фиксированным значением:
th:async |
th:autofocus |
th:autoplay |
th:checked |
th:controls |
th:declare |
th:default |
th:defer |
th:disabled |
th:formnovalidate |
th:hidden |
th:ismap |
th:loop |
th:multiple |
th:novalidate |
th:nowrap |
th:open |
th:pubdate |
th:readonly |
th:required |
th:reversed |
th:scoped |
th:seamless |
th:selected |
5.6 Установка значения любого атрибута (процессор атрибутов по умолчанию)
Thymeleaf предлагает процессор атрибутов по умолчанию, который позволяет нам устанавливать значение любого атрибута, даже если для него не определен th:* конкретный процессор в Standard Dialect.
Что-то вроде этого:
<span th:whatever="${user.name}">...</span>
Результатом будет:
<span whatever="John Apricot">...</span>
5.7 Поддержка аттрибутов, дружественных HTML5 и имен элементов
Также можно использовать совершенно другой синтаксис для применения процессоров к вашим шаблонам более удобным для HTML5 способом.
<table>
<tr data-th-each="user : ${users}">
<td data-th-text="${user.login}">...</td>
<td data-th-text="${user.name}">...</td>
</tr>
</table>
Синтаксис data-{prefix}-{name} является стандартным способом записи пользовательских атрибутов в HTML5, не требуя от разработчиков использования namespaced, таких как th:*. Thymeleaf делает этот синтаксис автоматически доступным для всех ваших диалектов (не только для Standard).
Существует также синтаксис для указания пользовательских тегов: {prefix}-{name}, который следует спецификации W3C Custom Elements (часть большой спецификации W3C Web Components). Это можно использовать, например, для элемента th:block (или th-block), который будет объяснен в следующем разделе.
Важно: этот синтаксис является дополнением к namespaced th:*, он не заменяет его. Нет никакого намерения вообще отказаться от namespaced синтаксиса в будущем.
lampa
Вставлю свои кровные пять копеек. Сначала пробовал freemaker, всё хорошо до поры до времени — когда нужно получать список одинаковых объектов из одной формы. Решил попробовать thymeleaf — тоже самое в целом.
Сейчас уже давно на JSP всё перевел. Но блин, почему шаблонизаторы вроде freemaker или thymeleaf так легко подключаются и почему чтобы установить JSP, надо прыгать с кровавым бубном?
Моё мнение, что начинать надо сразу с JSP, когда проект подразумевается больше формочки обратной связи.