Template file (*.tmpl)

The template file (* .tmpl) is the main rendering description file and contains three types of sections describing options, data and the template itself. For ease of development, it is easier to create a template either using the SublimeFCFPlugin, VSCodeFCFFramework plugins or the command:

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

Where:

TEMPLATE_NAME - Name of the new template

SUPER_TEMPLATE - The path to the base template. Optional parameter

Before examining the structure of a template in detail, let's give an example of it:

//~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>

As mentioned earlier, the template has three sections. Each section starts with the characters //~ followed by the name of the section in upper case. Sections form three types of template data that provide the rules for its display and behavior:

  • OPTIONS section - non-modifiable template data.
  • ARGUMENTS section - template arguments are data that can be redefined and changed.
  • TEMPLATE section - rendering instructions combining HTML and Javascript.

Accordingly, we have the OPTIONS, ARGUMENTS and TEMPLATE sections. Only the TEMPLATE section is required, other sections may not be declared.

Comments in templates (Since 1.1.46) All combinations starting with //~ characters and not containing the section type's service name are template comments.

Example:

//~~~~~~~~~~~~~~~~~~~~~~~ //~ This is main template //~~~~~~~~~~~~~~~~~~~~~~~ //~TEMPLATE main !{{Main template body}}! OPTIONS section

The OPTIONS section contains an object with a description of template options that do not change and describe its main program characteristics.

Template option values on the client are available through the fcf.NClient.Wrapper.getOptions() method. The description of the main options of the template is given below.

extends option
Contains the path to the base template from which the current one inherits. When a template is inherited, the OPTIONS and ARGUMENTS values are overloaded, and the contents of the template and sub-templates are replaced by the inheritor.
access option
An array containing the names of the roles that are allowed access to the template. An array element value equal to "*" allows access for all roles.
autoUpdate option
Template auto-update mode when changing its arguments. It can take one of several values:
  • true|"all" - The template is updated whenever the template argument changes by calling Wrapper.setArg()
  • "external" - A template update is performed when a template argument is changed that is initiated by external code and the change is not performed from a nested template. This mode is used when building the internal logic of the template visualization.
  • false - Template update fails when arguments change

The parameter can be overridden using the fcfAutoUpdate template argument.

Default value: false

clientRendering option

Render permission on the client. List of acceptable values:

  • true|"all" - Rendering and updating called on the browser side is done on the browser side.
  • "update" - The first rendering is done on the server side and the update is done on the browser side.
  • "update_np" - The first rendering is done on the server side and the update is done on the browser side. Program arguments are not recalculated when upgraded.
  • false - Rendering Performed on the server side only

The parameter can be overridden using the fcfClientRendering template argument.

Default value: false

include option
Array of JS and CSS files to be connected. JS files are also connected on the server side.
clientInclude option
An array of JS and CSS files to be connected, only on the browser side.
merge option
[Since 1.1.43] The DOM tree merge flag when updating the template. If true, then the existing elements are not replaced during the update, but are updated.

Default value: false

wrapper option

[Since version 1.1.36] Flag for creating a wrapper for the template. If the parameter is false, the template is not packaged in a container, a wrapper is not created for it, and its arguments are not available on the client.

Default value: true

static option

[Since 1.1.55] If the option is true, then DOM elements are not updated when the default template is updated. To update the DOM of template elements in the "static" mode, you must call the fcf.NClient.Wrapper.update() method or the fcf.NClient.Wrapper.refresh() method with the updateStatic flag.

Default value: false

lockTemplate option

The template displayed when blocking with the Wrapper.lock() method or false, then the blocking is performed only by the transparent container. If an option is not specified or true, the @controls:lock pattern is used. The parameter can be overridden using the fcfLockTemplate template argument.

Default value: true


ARGUMENTS section

The ARGUMENTS section stores an object with template arguments.

Template arguments are mutable template data and can be used both in rendering and on the browser side. Before a template argument is available for use, it must be declared in the //~ARGUMENTS section or passed as an argument when calling the template render.

Template arguments are of 2 types:

  1. Data not undergoing any processing and transmitted in direct form, as is.

    Example:

    //~ARGUMENTS { data: [{item1: 1}, {item2: 2}] }
  2. Data being assembled. This type of arguments is represented as an object with information about data collection rules. Each such object is tokenized before processing. Tokenization in the FCF framework is the substitution of the calculated value declared in the string element. The FCF tokenizer supports two substitution constructs:

    1. "@{{JAVASCRIPT_INSTRUCTION}}@" - JavaScript instruction for the calculated value.
    2. "!{{TRANSLATION_TEXT}}!" - Translation instruction. This type of instruction contains text that will be translated into the user's language during assembly, according to the application's translation set.

    When processing template arguments in tokenized constructs, the following variables are available:

    • object args - template arguments object
    • object decor - an object containing decor classes. The key is the code name of the class group, and the value is a string containing the CSS design classes. Formed by themes. So far, the functionality of themes has not been fully implemented.
    • fcf.RouteInfo route - object with route information

    Example:

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

    Result:

    123456789

    The assembly arguments are created by special functions and have several types:

    • An Argument value. Created by the fcf.argVal() function.
    • A Parameter URL argument. Created by the fcf.argURL() function. This type of argument automatically substitutes the value specified in the URL request and changes the URL address of the page when the value changes.
    • A link argument. Created by the fcf.argRef() function. Thanks to the reference, you can pass data stored in another template or argument.
    • An argument is a reference to a record element in a multiple output template (tables or sheets). Created by the fcf.argRecordRef() function.
    • A program argument. Created by the fcf.argProg() function. The argument data is generated programmatically in the hooksProgrammableArgument hook handler

System arguments

In addition to user-defined arguments, there are system arguments that start with the fcf prefix. Below is their description and purpose:

  • string fcfId - template identifier
  • string fcfClass - CSS classes added to the template header
  • string fcfClassInner - CSS classes added to the header of the template. This argument should only be used inside a template declaration and should not be overloaded by an external renderer.
  • string fcfStyle - CSS styles added to the template header
  • string fcfStyleInner - CSS styles added to the header of the template. This argument should only be used inside a template declaration and should not be overloaded by an external renderer.
  • bool|string fcfAutoUpdate - overloads the autoUpdate template option value
  • bool|string fcfClientRendering - overrides the value of the clientRendering template option, but only if the clientRendering parameter in the template options is not false
  • false|undefined|string fcfLockTemplate - overloads the value of the template option lockTemplate
  • string fcfEvent[EVENT_NAME] - DOM event handling variables of template action element. The variable name begins with the fcfEvent prefix, followed by the event name with a capital letter. The value is a string with Javascript code, in which the following variables are available:


    • Event event - Event object
    • fcf.NClient.Wrapper wrapper - Template wrapper object
    • fcf.NClient.Wrapper parent - Template parent wrapper


    Example:

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

TEMPLATE section

In the template section, the rules for generating HTML are written.

The template section has three control constructs: %{{ }}% code construct, @{{ }}@ output construct and !{{ }}! translate construct

Code construction %{{ }}% This block contains the Javascript control code. When using blocks if, while, for and others inside which the break of the construction %{{ }}% is used, brackets { } should be used. Also, this construction supports the use of asynchronous operations - the await construction.

Example

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

Result

<div>Hello World!</div> <div>Hello World!</div> <div>Hello World!</div> Translation construct !{{ }}! Outputs text to a template using translation to the user's language.

Example

!{{Hello world}}! Output construct @{{ }}@ This block performs data output to the body of the template. Also, this construction supports the use of asynchronous operations - the await construction.

Example

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

Result

<p>first</p> <p>second</p> <p>third</p> Output runtime construct #{{}}#

Starting from version 1.1.54, the framework has a runtime construct for displaying the status of template arguments #{{}}#. This construct is similar to the @{{}}@ output construct, but when you change a template argument that was routed to output via the #{{}}# output construct, the value in the DOM tree is automatically updated without calling the template renderer. However, due to the fact that the framework has to work directly with DOM elements, the #{{}}# construct has restrictions on usage and can be used either as rendered content or as attributes of a DOM element. In addition to template arguments, variables declared in the template can be used in the #{{}}# construction, their values ​​are simply passed to the browser, due to which the output instruction is processed independently of the rendering of the main template.

An example of using the construction #{{}}#

//~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>

In this example, the template arguments are edited by the @controls:text-edit controls, and the result of the change is immediately displayed in the browser.

Result

Variables available in a template

In addition to user-defined variables, the following variables are available in a template:

  • object args - template arguments object
  • object decor - an object containing the decoration classes. The key is the code name of the class group, and the value is a string containing CSS design classes. Formed by themes. The functionality of the themes has not yet been fully implemented. Not available in construction #{{}}#
  • fcf.RouteInfo route - route information object. Not available in construction #{{}}#
  • fcf.NRender.NDetails.TemplateRender render - The internal renderer of a template. Not available in construction #{{}}#

Declaring events in a template

In addition to the standard method of declaring event handlers of the DOM element, the developer can declare events via the fcfEvent[EVENT_NAME] attributes. Unlike regular events, additional variables are available in the event handler code:

  • Event event - Event object
  • fcf.NClient.Wrapper wrapper - Template wrapper object
  • fcf.NClient.Wrapper parent - Template parent wrapper

Example:

//~TEMPLATE <a fcfEventClick="wrapper.onClick(event)">Link</a> Subtemplates

In addition to the main sections, subtemplate sections can be declared in the template. They are declared in the same way as the main sections, only after the section type, followed by a space, the name of the subtemplate.

To render the subtemplate, a path is used that has the format: [MAIN_TEMPLATE_PATH]+[SUBTEMPLATE_NAME]

Where:

MAIN_TEMPLATE_PATH - path to the main template

SUBTEMPLATE_NAME - Subtemplate name


If rendering is performed inside the main template, then the full path may not be specified: +[SUBTEMPLATE_NAME]

Here's an example of a template:

//~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>

Result:

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

As you can see from the example, the child template is rendered through the "+item" path:

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