Рендеринг шаблона Рендеринг шаблона в фреймворке FCF может выполняться из разных участков WEB приложения: из тела шаблона, из аргумента шаблона, из хука шаблона, из браузера и из кода сервера. Все эти пять случаев отличаются между собой.

В данном разделе мы познакомимся со следующими видами рендеринга:

Рендеринг из шаблона

Чаще всего при построении WEB приложения используется именно этот вид рендеринга, он может выполняться, как в конструкциях кода %{{ }}%, так и в конструкциях вывода @{{ }}@.

Для рендеринга шаблона применяется метод render.template(), внутреннего объекта шаблона render. Первым параметром данного метода выступает путь к шаблону, а вторым аргументы шаблона.

Приведем пример рендеринга шаблона на базе бланка приложения ($ fcfmngr create project test). Файл :templates/pages/main-page.tmpl:

//~OPTIONS { // Basic inheritance template extends: ":templates/super/page.tmpl", } //~ARGUMENTS body { } //~TEMPLATE body %{{ let textEdit = await render.template("@controls:text-edit", { value: "text", width: "100%"}); }}% <p> @{{textEdit}}@ </p> <p> @{{ render.template("@controls:textarea", { value: "some text", width: "100%"}); }}@ </p>

В данном примере мы выполняем рендеринг двух шаблонов из пакета fcfControls по их псевдонимам: "@controls:text-edit" - поле ввода и "@controls:textarea" - поле ввода многострочного текста.

Рендеринг выполняется в конструкции кода %{{}}% и в конструкции вывода @{{}}@. Но в конструкции кода выполняется ожидание завершения операции, через оператор await, после чего результат записывается в переменную textEdit, которая выводится в шаблон через операцию вывода @{{}}@.

Для операций вывода оператор await не требуется, шаблонизатор самостоятельно определяет, что на вывод направлен объект Promise или fcf.Actions

Путь шаблона может быть задан либо прямым путем к шаблону, либо псевдонимом, которые начинаются с символа @, для упрощенного обращения к часто используемому ресурсу. Псевдонимы задаются в параметре конфигурации aliases. Так в пакете fcfControls для полей ввода определены псевдонимы:

Файл : fcfControls:package.config

{ ... aliases: { ... "controls:text": "fcfControls:templates/text.tmpl", ... "controls:textarea": "fcfControls:templates/textarea.tmpl", ... } ... }

Результат рендеринга приведен ниже.

Рендеринг из аргумента шаблона

Бывают случаи когда рендеринг шаблона удобней выполнять просто объявлением аргумента шаблона, для этого применяется шаблонный аргумент, создаваемый функцией fcf.argTmpl()

Данный тип аргументов раскрывается в шаблон при сборке аргументов родительского шаблона.

В качестве первого параметра функции fcf.argTmpl() выступает путь/имя шаблона, а в качестве второго его аргументы.

Для примера приведем вывод диалога с кнопкой, созданной шаблонным аргументом. Шаблон диалога из пакета fcfControls с псевдонимом @controls:dialog, имеет аргумент buttons, который должен быть массивом со строками содержащими HTML элементы.

Пример файла страницы :templates/pages/main-page.tmpl созданной на базе бланка приложения ($ fcfmngr create project test).

//~OPTIONS { // Basic inheritance template extends: ":templates/super/page.tmpl", } //~ARGUMENTS body { } //~TEMPLATE body @{{ render.template( "@controls:dialog", { content: "Hello to this beautiful world!", buttons: fcf.argVal([ "***", fcf.argTmpl("@controls:button", {title: "Close dialog", fcfEventClick: "parent.close()"}), "***", ]) }); }}@

Обратите внимание, что функция fcf.argTmpl() вызывается внутри аргумента, созданного функцией fcf.argVal(), это необходимо, так как при обработке аргументов шаблона простые значения (объекты и массивы) не анализируются на вложенные аргументы и над ними не выполняется токенизация. Для того что бы сборщик шаблона обработал вложенный аргумент с нашей кнопкой, мы применили аргумент шаблона, созданный вызовом fcf.argVal().

Результат рендеринга:

Рендеринг из обработчика хука

Рендеринг из обработчика хука выполняется методом fcf.NRender.TaskInfo.render(). Приведем небольшой пример на базе базового проекта созданного командой: $fcfmngr create project

Шаблон страницы :templates/pages/main-page.tmpl: //~OPTIONS { // Basic inheritance template extends: ":templates/super/page.tmpl", } //~OPTIONS body { autoUpdate: true, } //~ARGUMENTS body { templateName: "+block", block: fcf.argProg(), } //~TEMPLATE body <a fcfEventClick="wrapper.setArg('templateName', '+block')">Show first block</a> | <a fcfEventClick="wrapper.setArg('templateName', '@controls:button')">Show button</a> | <a fcfEventClick="wrapper.setArg('templateName', '@controls:text-edit')">Show text-edit</a> <hr> @{{args.block}}@ //~TEMPLATE block <h3>Example rendering from hooks</h3>

Файл обработчиков хуков :templates/pages/main-page+body.hooks.js

fcf.module({ name: "templates/pages/main-page+body.hooks.js", dependencies: [], module: function(){ return { // // Object of hooks for programmatically populated arguments // hooksProgrammableArgument: { // // Hook of the assembly of a programmatically populated argument created by the fcf.argProg() method with the name ARG_NAME // @result Returns the value of an argument or a Promise object // block: (a_taskInfo) => { return a_taskInfo.render(a_taskInfo.args.templateName); }, }, }; } });

Как видно из кода файлов при нажатии на ссылки будет выполнятся перерисовка шаблона, т.к. параметр autoUpdate равен true. Путь шаблона задается при клике на ссылку методом Wrapper.setArg. Сам шаблон отрисовывается в файле :templates/pages/main-page+body.hooks.js в переменную block, которая выводится в чистом виде в основной шаблон:

Рендеринг шаблона вне шаблонизатора на стороне сервера

Бывают случаи когда необходимо выполнить рендеринг вне штатных механизмов шаблонизатора, к примеру в кастомном контроллере, при отпрвки письма или в другом случае. Тогда используется метод fcf.application.render()

Приведем пример рендеринга шаблона кнопки методом fcf.application.render():

let template = await fcf.application.render({ template: "@controls:button", args: { title: "Hello World!" } }); console.warn("", template.content);

Result:

<div fcftemplate="fcfControls:templates/button.tmpl" id='_4e508c3cd14a3989363d57084f2a4605' class=' fcfwrapper ' ><button autocomplete="off" style="width:auto" class="fcf-button ">Hello World!</button></div>

Рендеринг шаблона вне шаблонизатора на стороне клиента

На стороне клиента рендеринг выполняется функцией fcf.NClient.Application.render() объекта fcf.application

Приведем пример вывода диалога при нажатии на ссылку. Пример создадим на базе бланка приложения созданного командой:

$ fcfmngr create project test

Файл тела страницы :templates/pages/main-page.tmpl будет иметь вид:

//~OPTIONS { // Basic inheritance template extends: ":templates/super/page.tmpl", } //~TEMPLATE body <a fcfEventClick="wrapper.onClick()">Show dialog</a>

Рендеринг диалога мы будем выполнять в методе onClick враппера шаблона :templates/pages/main-page+body.wrapper.js

fcf.module({ name: "templates/pages/main-page+body.wrapper.js", dependencies: [":templates/super/page+body.wrapper.js"], module: function(Wrapper){ return class WrapperEx extends Wrapper{ constructor(a_initializeOptions){ super(a_initializeOptions); } onClick(){ fcf.application.render({ template: "@controls:dialog", owner: document.body, args: { content: "Hello world!" } }) } }; } });

Как видно из примера, шаблон помещается в document.body, как указано в параметре owner.

Теперь, если мы запустим приложение, откроем в браузере адрес http:localhost:8080.

$ fcfserver ./server.json

После нажатия на ссылку мы увидим вывод нашего диалога.