4.2.4. Шаблон HTML

Шаблон HTML задается в файле c расширением .html в кодировке UTF-8 (без BOM). При создании HTML/CSS шаблона вы можете пользоваться библиотекой Flying Saucer, руководство по ее использованию находится по адресу http://flyingsaucerproject.github.io/flyingsaucer/r8/guide/users-guide-R8.html

Размер страницы, наличие и расположение хэдеров и футеров настраиваются с помощью CSS. Пример отчёта с повторяющимися блоками хэдера и футера доступен в разделе Примеры отчётов.

Существует два способа для размещения данных в шаблоне:

  • Использовать тэги FreeMarker.

  • Использовать шаблонизатор Groovy.

По умолчанию мастер отчётов создает HTML-шаблон с тэгами FreeMarker.

Для переключения между способами используйте переключатель Template type в редакторе шаблонов.

html template editor
Рисунок 39. Редактор HTML шаблона
Шаблонизатор Groovy

Шаблон отчёта HTML может быть предварительно обработан как шаблон Groovy с помощью шаблонизатора GStringTemplateEngine.

Шаблонизатор использует стиль JSP скриптов <% %> и синтаксис выражений <%= %>, или стиль выражений GString. Переменная out осуществляет вывод в файл, для которого используется шаблон. Таким образом, шаблон может использовать любой код на Groovy, если он правильно определен. GStringTemplateEngine имеет доступ к:

  • внешним параметрам отчёта: BandName.fields.ParamName;

  • полосам отчёта: BandName.bands.ChildBandName;

  • полям: BandName.fields.FieldName.

Для удобства можно использовать переменные:

<% def headerRow = Root.bands.HeaderRow %>
<p>Date: ${headerRow.fields.reportDate}</p>

Ниже приведен пример шаблона, который выводит отчёт для выбранного пользователя.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
    <head>
        <title> Report User </title>
        <style type="text/css">
 body {font-family: 'Charis SIL', sans-serif;} tbody tr {height:20px; min-height:20px}
        </style>
    </head>
    <body>
        <% def user = Root.bands.User %>
        <p>Login: ${user.fields.login.first()}</p>
        <p>Active: ${user.fields.active.first()}</p>
    </body>
</html>

Пример отчёта с использованием Groovy шаблонизатора доступен в разделе Примеры отчётов.

FreeMarker

Документация по FreeMarker находится по адресу https://freemarker.apache.org/docs/.

Модель документа FreeMarker имеет следующую структуру:

Band {
      bands [ bandName : [ band, .. ], .. ]
      fields [ fieldName : fieldValue, .. ]
}

Например, для доступа к полю name в полосе band в нулевой строке выборки используйте следующее выражение:

Root.bands.band[0].fields.name

Для удобства можно использовать переменные:

<#assign headerRow = Root.bands.Header[0]>
<p>Date: ${headerRow.fields.reportDate}</p>

Для получения локализованных значений можно использовать функции getMessage() и getMainMessage() :

  • getMessage() используется для получения локализаций enum или, если передано два строковых параметра (msgPack, key), для получения по ключу сообщения из указанного пакета сообщений:

    ${getMessage(order.status)}
  • getMainMessage(), в свою очередь, принимает один строковый параметр key и ищет по данному ключу сообщение в главном пакете сообщений:

    ${getMessage(outOfStockMessage)}

Пример шаблона для вывода отчёта, состоящего из двух полос: Book и Authors, первая из которых выводит название и жанр книги, а вторая – список авторов этой книги:

<!doctype html>
<html>
<head></head>
<body>
    <#assign book = Root.bands.Book[0] />
    <#assign authors = Root.bands.Authors />

    <p>Name: ${book.fields.name}</p>
    <p>Genre: ${book.fields.literatureType.name}</p>
    <table border="1" cellpadding="5" cellspacing="0" width="200">
        <thead>
        <tr>
            <td>First name</td>
            <td>Last name</td>
        </tr>
        </thead>
        <tbody>
        <#list authors as author>
            <tr>
                <td>${author.fields.firstName}</td>
                <td>${author.fields.lastName}</td>
            </tr>
        </#list>
        </tbody>
    </table>
</body>
</html>

Более сложный пример. Имеем структуру полос следующего вида:

Root {
    HeaderBand {
        query = return [[ "name" : "Column1" ],[ "name" : "Column2" ]]
    }
    Band1 {
        query = return [
            ["field1" : "Value 11", "field2" : "Value 12"],
            ["field1" : "Value 21" , "field2" : "Value 22"]
        ]
    }
    Band2 {
        query = return [[ "header" : "Header1" ], [ "header" : "Header2" ]]
        SubBand1 {
            query = return [["header" : 'SubHeader1'] , [ "header" : 'SubHeader2' ]]
        }
    }
}
  • Обращение к полю:

    <!doctype html>
    <html>
        <head>
            <title> Simple template </title>
        </head>
        <body>
        <#assign Tree1 = Root.bands.Band2>
            <h1> Header </h1>
            <p>
                ${Tree1[1].bands.SubBand1[0].fields.header}
            </p>
        </body>
    </html>
  • Список:

    <!doctype html>
    <html>
        <head>
            <title> List </title>
        </head>
        <body>
        <#assign Table1Header = Root.bands.HeaderBand>
    
            <#if Table1Header?has_content>
                <ol>
                    <#list Table1Header as header>
                        <li> ${header.fields.name} </li>
                    </#list>
                </ol>
            </#if>
        </body>
    </html>
  • Таблица:

    <!doctype html>
    <html>
    <head>
        <title> Table </title>
    </head>
    <body>
    <#assign Table1Header = Root.bands.HeaderBand>
        <#assign Table1 = Root.bands.Band1>
            <table border="1" cellpadding="5" cellspacing="0" width="200">
                <thead>
                <tr>
                    <#list Table1Header as header>
                        <td> ${header.fields.name} </td>
                    </#list>
                </tr>
                </thead>
                <tbody>
                <#list Table1 as row>
                    <tr>
                        <td>
                            ${row.fields.field1}
                        </td>
                        <td>
                            ${row.fields.field2}
                        </td>
                    </tr>
                </#list>
                </tbody>
            </table>
    </body>
    </html>
  • Многоуровневый список:

    <!doctype html>
    <html>
    <head>
        <title> Multi-level list </title>
    </head>
    <body>
    <#assign Tree1 = Root.bands.Band2>
        <ul>
            <#list Tree1 as item>
                <li>
                    <h2> ${item.fields.header} </h2>
                    <#if item.bands.SubBand1?has_content>
                        <ul>
                            <#list item.bands.SubBand1 as subitem>
                                <li>
                                    <h3> ${subitem.fields.header} </h3>
                                </li>
                            </#list>
                        </ul>
                    </#if>
                </li>
            </#list>
        </ul>
    </body>
    </html>
Добавление изображений

В настоящий момент генератор отчётов CUBA не позволяет вставлять изображения в HTML-отчёты так же, как это реализовано для шаблонов DOCX/XLSX. Тем не менее, изображения можно добавить, используя тег img со ссылкой на изображение в атрибуте src. Вставить изображения в HTML-шаблон можно одним из перечисленных ниже способов.

  • по URL

    Изображения хранятся на сервере Tomcat или другом хостинге. К примеру, для вставки изображения, хранящегося в deploy\tomcat\webapps\ROOT\images, используется следующий код:

<img src="http://localhost:8080/images/SomeImage.jpg" height="68" width="199" border="0" align="right"/>
  • с использованием Bitmap

    Ссылка на изображение в виде байтового массива вставляется в атрибут src. В этом случае удобно использовать переменные для атрибутов сущностей, являющихся ссылкой на FileDescriptor. Строку ByteArray можно вставить в атрибут и напрямую, однако мы не рекомендуем этот подход к использованию:

<img alt="SomePicture.png" src="data:image/png;base64,iVBORw0K ..... AcEP9PwxD0hNKK1FCAAAAAElFTkSuQmCC"/>
  • с использованием специальных префиксов:

    • С помощью префиксов core:// и web:// можно ссылаться на ресурсы изображений из web или core модулей без необходимости жестко кодировать webPort и webContextName в шаблоне. Например, изображение, размещенное в каталоге deploy\tomcat\webapps\app\VAADIN\images может быть вставлено как:

      <img src="web://VAADIN/images/SomeImage.jpg" height="68" width="199" border="0" align="right"/>
    • Префикс fs:// используется для вставки изображения по идентификатору объекта типа FileDescriptor. Например:

      <img src="fs://fede432a-4f5d-3bab-71a0-b98133759b0f" height="68" width="199" border="0" align="right"/>
Встроенный редактор

Вы можете редактировать шаблоны HTML на лету. Встроенный текстовый редактор в окне Template editor позволяет вносить изменения в отчёт без необходимости заново загружать файл шаблона.

html report editor
Рисунок 40. Встроенный редактор HTML