Файл шаблона (*.tmpl)

Файл шаблона (*.tmpl) является основным файлом описания рендеринга и содержит три вида секций описывающие опции, данные и сам шаблон. Для удобства разработки проще создавать шаблон либо используя плагин SublimeFCFPlugin, VSCodeFCFFramework либо команду:

$ fcfmngr create template-file [TEMPLATE_NAME] [SUPER_NAME]

Где:

TEMPLATE_NAME - Имя нового шаблона

SUPER_TEMPLATE - Путь к базовому шаблону. Необязательный параметр

Перед подробным рассмотрением структуры шаблона приведем его пример:

//~OPTIONS { // Basic inheritance template // Default: undefined //extends:"",
// An array of roles that have permission to access the template
// Default: ["*"]
//access: ["*"],
// Automatic template update mode when the argument changes. // Acceptable values: // true|"all" - The update is performed on any change // "external" - The update is performed only if the external template was the initiator of the change. // false - The template is not being updated // The option can be overridden by the fcfAutoUpdate template argument. // Default: false //autoUpdate: false, // If true, the rendering is performed on the client side. // Acceptable values: // true|"all" - Rendering is done on the client, when done on the browser side // "update" - The first render is done on the server side and the update is on the client side // "update_np" - The first render is done on the server side and the update is on the client side. // Parameters of the programmable type are not recalculated. // false - Rendering is always done on the server side // This parameter can be overridden by the fcfClientRendering template argument, but only if the option is true. // Default: false //clientRendering: false, // Additional JS & CSS files to connect (JS files are also connected on the server side) // Default: [] //include: [], // Plug-in additional JS & CSS files on the client side // Default: [] //clientInclude: [], // If the parameter is false, the template is not wrapped in a container, // a wrapper is not created for it, and its arguments are not available on the client. // Default: true //wrapper: true,
// DOM elements merge flag. // If true, then existing items are not replaced when updated, but updated. // Default: false //merge: false,
// If set to true, the DOM elements are not changed by default when the template is updated.
// To update DOM elements on update, you need to call the update|reload|refresh methods with the updateStatic flag.
// Default: false
//static: false,
// The template is displayed when the template is locked or false, // then the lock is performed only by the transparent container. // If the option is true, then @controls:lock is used. // The option can be overridden by the fcfLockTemplate template argument. // Default: true //lockTemplate: true } //~ARGUMENTS { } //~TEMPLATE <h1>Hello wonderful world!</h1>

Как упоминалось ранее, шаблон имеет три секции. Каждая секция начинается с символов //~, после которой следует имя секции в верхнем регистре. Секции формируют три типа данных шаблона, которые описывают правила его отображения и поведения:

  • Секция OPTIONS - не изменяемые данные шаблона.
  • Секция ARGUMENTS - аргументы шаблона - данные, которые могут быть переопределены и изменены.
  • Секция TEMPLATE - инструкции рендеринга, совмещающие в себе HTML и Javascript.

Соответственно имеем секции OPTIONS, ARGUMENTS и TEMPLATE. Только секция TEMPLATE является обязательной, остальные секции могут быть не объявлены.

Комментарии в шаблоне (Начиная с версии 1.1.46) Все комбинации начинающиеся с символов //~ и не содержащие служебное название типа секции являются комментариями шаблона.

Пример:

//~~~~~~~~~~~~~~~~~~~~~~~ //~ This is main template //~~~~~~~~~~~~~~~~~~~~~~~ //~TEMPLATE main !{{Main template body}}! Секция OPTIONS

Секция OPTIONS содержит в себе объект с описанием опций шаблона которые не меняются и описывают его основные программные характеристики.

Значения опций шаблона на клиенте доступны через метод fcf.NClient.Wrapper.getOptions(). Описание основных опций шаблона приведено ниже.

Опция extends
Содержит в себе путь к базовому шаблону, от которого наследуется текущий. При наследовании шаблона происходит перегрузка значений OPTIONS и ARGUMENTS, а содержимое шаблона и подшаблонов подменяется наследником.
Опция access
Массив содержащий имена ролей для которых разрешен доступ к шаблону. Значение элемента массива равное "*" разрешает доступ для всех ролей.
Опция autoUpdate
Режим автообновления шаблона при изменении его аргументов. Может принимать одно из нескольких значений:
  • true|"all" - Обновление шаблона выполняется при любом изменении аргумента шаблона вызовом метода Wrapper.setArg()
  • "external" - Обновление шаблона выполняется при изменении аргумента шаблона инициатором которого является внешний код и изменение выполняется не из вложенного шаблона. Данный режим используется при построении внутренней логики визуализации шаблона.
  • false - Обновление шаблона не выполняется при изменении аргументов

Параметр можно переопределить с помощью аргумента шаблона fcfAutoUpdate.

Значение по умолчанию: false

Опция clientRendering

Разрешение рендеринга на клиенте. Перечень допустимых значений:

  • true|"all" - Рендеринг и обновление вызываемое на стороне браузера выполняется на стороне браузера.
  • "update" - Первый рендеринг выполняется на стороне сервера, а обновление происходит на стороне браузера.
  • "update_np" - Первый рендеринг выполняется на стороне сервера, а обновление происходит на стороне браузера. При обновлении программные аргументы не пересчитываются.
  • false - Рендеринг Выполняется только на стороне сервера

Параметр можно переопределить с помощью аргумента шаблона fcfClientRendering.

Значение по умолчанию: false

Опция include
Массив подключаемых JS и CSS файлы. JS файлы подключаются так же на стороне сервера.
Опция clientInclude
Массив подключаемых JS и CSS файлов, только на стороне браузера.
Опция merge
[С версии 1.1.43] Флаг слияния DOM дерева при обновлении шаблона. Если true, то существующие элементы при обновлении не заменяются, а обновляются.

Значение по умолчанию: false

Опция wrapper

[С версии 1.1.36] Флаг создания враппера для шаблона. Если параметр равен false, шаблон не упаковывается в контейнер, для него не создается оболочка, а его аргументы недоступны на клиенте.

Значение по умолчанию: true

Опция static

[Since 1.1.55] Если опция равна true, то обновление DOM элементов при обновлении шаблона по умолчанию не выполняется. Для обновления DOM элеметов шаблона в режиме "static" необходимо взывать метод fcf.NClient.Wrapper.update() или метод fcf.NClient.Wrapper.refresh() с флагом updateStatic.

Значение по умолчанию: false

Опция lockTemplate

Шаблон отображаемый, при блокировки методом Wrapper.lock() или false, тогда блокировка выполняется только прозрачным контейнером. Если опция не указана или равна true, используется шаблон @controls:lock. Параметр можно переопределить с помощью аргумента шаблона fcfLockTemplate.

Значение по умолчанию: true

Секция ARGUMENTS

Секция ARGUMENTS хранит в себе объект с аргументами шаблона.

Аргументы шаблона являются изменяемыми данными шаблона и могут быть использованы как в рендере, так и на стороне браузера. Перед тем как аргумент шаблона будет доступен для использования он должен быть объявлен в секции //~ARGUMENTS или передан в качестве аргумента при вызове рендеринга шаблона.

Аргументы шаблона бывают 2-х типов:

  1. Данные не проходящие никакой обработки и передающиеся в прямом виде, как есть.

    Пример:

    //~ARGUMENTS { data: [{item1: 1}, {item2: 2}] }
  2. Данные проходящие сборку. Данный тип аргументов представляется в виде объекта с информацией о правилах сборки данных. Каждый такой объект перед обработкой проходит токенизацию. Токенизация в фреймворке FCF - это подстановка расчетного значения объявленного в строковом элементе. В токенизаторе FCF поддерживаются две конструкции подстановки:

    1. "@{{JAVASCRIPT_INSTRUCTION}}@" - JavaScript инструкция расчетного значения.
    2. "!{{TRANSLATION_TEXT}}!" - Инструкция перевода. В данном типе инструкций размещается текст, который при сборке будет переведен на язык пользователя, в соответствии с набором переводов приложения.

    При обработке аргументов шаблона в токенизируемых конструкциях доступны следующие переменные:

    • object args - объект аргументов шаблона
    • object decor - объект содержащий классы оформления. В качестве ключа выступает кодовое имя группы классов, а в качестве значения строка содержащая CSS классы оформления. Формируется темами оформления. Пока функционал тем не реализован в полной мере.
    • fcf.RouteInfo route - объект с информацией о маршруте

    Example:

    //~ARGUMENTS { val1: "12345", val2: fcf.argVal("@{{args.val1}}@6789"), } //~TEMPLATE @{{args.val2}}@

    Result:

    123456789

    Аргументы проходящие сборку создаются специальными функциями и имеют несколько типов:

    • Аргумент значение. Создается функцией fcf.argVal().
    • Аргумент URL параметра. Создается функцией fcf.argURL(). Данный тип аргумента автоматически подставляет значение указанное в URL запросе и при изменении значения меняет URL адрес страницы.
    • Аргумент ссылка. Создается функцией fcf.argRef(). Благодаря ссылке можно передать данные хранящиеся в другом шаблоне или аргументе.
    • Аргумент ссылка на элемент записи в шаблоне множественного вывода (таблицы или листы). Создается функцией fcf.argRecordRef().
    • Программный аргумент. Создается функцией fcf.argProg(). Данные аргумента формируются программно в обработчике хука hooksProgrammableArgument

Системные аргументы

Помимо аргументов определенных пользователем, имеются системные аргументы, имя которых начинается с префикса fcf. Ниже представлено их описание и назначение:

  • string fcfId - идентификатора шаблона
  • string fcfClass - CSS классы добавляемые в заголовок шаблона
  • string fcfClassInner - CSS классы добавляемые в заголовок шаблона. Данный аргумент должен использоваться только внутри объявления шаблона и не перегружаться внешним рендером
  • string fcfStyle - CSS стили добавляемые в заголовок шаблона
  • string fcfStyleInner - CSS стили добавляемые в заголовок шаблона. Данный аргумент должен использоваться только внутри объявления шаблона и не перегружаться внешним рендером
  • bool|string fcfAutoUpdate - перегружает значение опции шаблона autoUpdate
  • bool|string fcfClientRendering - перегружает значение опции шаблона clientRendering, но только если параметр clientRendering в опциях шаблона не равен false
  • false|undefined|string fcfLockTemplate - перегружает значение опции шаблона lockTemplate
  • string fcfEvent[EVENT_NAME] - переменные обработки события DOM элемента действий шаблона. Имя переменной начинается с префикса fcfEvent, после следует имя события с заглавной буквы. Значение представляет из себя строку с Javascript кодом, в котором доступны следующие переменные:


    • Event event - Объект события
    • fcf.NClient.Wrapper wrapper - Объект враппера шаблона
    • fcf.NClient.Wrapper parent - Враппер родителя шаблона


    Пример:

    //~ARGUMENTS { fcfEventClick: "wrapper.onClick()", }

Секция TEMPLATE

В секции шаблона записываются правила формирования HTML.

Секция шаблона имеет три управляющие конструкции: конструкция %{{ }}% кода, конструкция вывода @{{ }}@ и конструкция перевода !{{ }}!

Конструкция кода %{{ }}% Данный блок содержит управляющий код Javascript. При использовании блоков if, while, for и других внутри которых применяется разрыв конструкции %{{ }}%, должны использоваться скобки { }. Также, данная конструкция поддерживает применение асинхронных операций - конструкции await.

Пример

//~TEMPLATE %{{ let i = 0; while(i < 3) { }}% <div>Hello World!</div> %{{ ++i; } }}%

Результат

<div>Hello World!</div> <div>Hello World!</div> <div>Hello World!</div> Конструкция перевода !{{ }}! Выводит текст в шаблон с применением перевода на язык пользователя.

Пример

!{{Hello world}}! Конструкция вывода @{{ }}@ Данный блок выполняет вывод данных в тело шаблона. Также, данная конструкция поддерживает применение асинхронных операций - конструкции await.

Пример

%{{ let array = ["first", "second", "third"]; for(let i = 0; i < array.length; ++i) { }}% <p>@{{array[i]}}@</p> %{{ } }}%

Результат

<p>first</p> <p>second</p> <p>third</p> Конструкция runtime вывода #{{}}#

Начиная с версии 1.1.54 в фреймворке доступна конструкция runtime вывода состояния аргументов шаблона #{{}}#. Данная конструкция аналогична конструкции вывода @{{}}@, но при изменении аргумента шаблона, который был направлен на вывод, через конструкцию вывода #{{}}#, значение в DOM дереве автоматически обновляется, без вызова рендеринга шаблона. Однако, ввиду того что фреймворку приходится работать непосредственно с DOM элементами, конструкция #{{}}# имеет ограничения на использования и может быть использована, либо в качестве выводимого контента, либо в виде атрибутов DOM элемента. Помимо аргументов шаблона, в конструкции #{{}}# могут быть использованы переменные объявленные в шаблоне, их значения просто передаются в браузер, благодаря чему инструкция вывода обрабатывается независимо от рендеринга основного шаблона.

Пример использования конструкции #{{}}#

//~ARGUMENTS body { content: "Content", class: "black", paddingLeft: 0, } //~TEMPLATE body <fieldset> <legend>Example</legend> <div class="#{{args.class}}#" style="padding-left: #{{args.paddingLeft}}#px">#{{args.content}}#</div> </fieldset> <p> "content" argument: @{{ render.template("@controls:text-edit", {value: fcf.argRef("content")}) }}@ </p> <p> "class" argument: @{{ render.template("@controls:text-edit", {value: fcf.argRef("class")}) }}@ </p> <p> "paddingLeft" argument: @{{ render.template("@controls:text-edit", {value: fcf.argRef("paddingLeft")}) }}@ </p>

В данном примере аргументы шаблона редактируются контролами @controls:text-edit, а результат изменения сразу отображается в браузере.

Результат

Переменные доступные в шаблоне

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

  • object args - объект аргументов шаблона
  • object decor - объект содержащий классы оформления. В качестве ключа выступает кодовое имя группы классов, а в качестве значения строка содержащая CSS классы оформления. Формируется темами оформления. Пока функционал тем не реализован в полной мере. Не доступен в конструкции #{{}}#
  • fcf.RouteInfo route - объект с информацией о маршруте. Не доступен в конструкции #{{}}#
  • fcf.NRender.NDetails.TemplateRender render - Внутренний объект рендера шаблона Не доступен в конструкции #{{}}#.

Объявление событий в шаблоне

Помимо штатного метода объявления обработчиков событий DOM элемента, разработчик может объявлять события через атрибуты fcfEvent[EVENT_NAME]. В отличии от штатных событий в коде обработчика события доступны дополнительные переменные:

  • Event event - Объект события
  • fcf.NClient.Wrapper wrapper - Объект враппера шаблона
  • fcf.NClient.Wrapper parent - Враппер родителя шаблона

Пример:

//~TEMPLATE <a fcfEventClick="wrapper.onClick(event)">Link</a> Подшаблоны

Помимо основных секций в шаблоне могут быть объявлены секции подшаблона. Объявляются они аналогично основным секциям, только после типа секции, через пробел следует имя подшаблона.

Для рендеринга подшаблона используется путь, который имеет формат: [MAIN_TEMPLATE_PATH]+[SUBTEMPLATE_NAME]

Где:

MAIN_TEMPLATE_PATH - путь к основному шаблону

SUBTEMPLATE_NAME - Имя подшаблона


Если рендеринг выполняется внутри основного шаблона то полный путь может быть не указан: +[SUBTEMPLATE_NAME]

Приведем пример шаблона:

//~TEMPLATE <h1>Example of the simple list</h1> %{{ let list = [ {name: "first", value: "value 1"}, {name: "second", value: "value 2"}, {name: "third", value: "value 3"}, ]; list.forEach((a_item)=>{ }}% @{{ render.template("+item", {value: a_item}) }}@ %{{ }); }}% //~TEMPLATE item <div> <b>@{{args.value.name}}@</b> - @{{args.value.value}}@ </div>

Результат:

<h1>Example of the simple list</h1> <div> <b>first</b> - value 1 </div> <div> <b>second</b> - value 2 </div> <div> <b>third</b> - value 3 </div>

Как видно из примера рендеринг дочернего шаблона выполняется через путь "+item":

render.template("+item", {value: a_item})