General description of the application template operation
To build an application, we need to familiarize ourselves with the rules for building templates.
The main mechanism for displaying and processing content of the FCF framework is templates. A template can consist of 4 types of files or only one .tmpl if additional functionality is not required.
Each file type is described in the kernel description:
Check out the structure of the template from the above descriptions. You should also consider how rendering is performed in the FCF template:
FCF templates support the concept of inheritance, which allows you to create templates and application pages of the same type. Our base application framework, created by the command $ fcfmngr create project fcf-example-planet, is also based on inheritance. The main page :templates/pages/main-page.tmp inherits from the base template :templates/super/page.tmpl, and the page body content is located in the "body" sub-template
Consider the base template :templates/super/page.tmpl from which the main page inherits.
//~OPTIONS
{
// Basic inheritance template
// Default: undefined
// extends:"<super_template.tmpl>",
// 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
// 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:[":templates/css/styles.css"],
// [Since 1.1.43] DOM elements merge flag.
// If true, then existing items are not replaced when updated, but updated.
// Default: false
merge: false,
// 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,
// 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
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
@{{ render.header(); }}@
</head>
<body>
<div class="header">
<div class="header-title">
<a href="/">!{{FCF Application}}!</a>
</div>
<div class="header-controls">
<div class="header-controls-line">
%{{ if (fcf.getContext().session.user.user) { }}%
<span class="header-control">!{{User}}!: @{{fcf.getContext().session.user.user}}@</span>
%{{ if (fcf.getContext().session.user.roles.root) { }}%
<span class="header-control"><a href="/fcfpackages/fcfManagement">!{{System settings}}!</a></span>
%{{ } }}%
<span class="header-control"><a fcfEventClick="wrapper.onLogout()">!{{Logout}}!</a></span>
%{{ } else { }}%
%{{ if (fcf.application.getConfiguration().fcfSimpleAuthorization_enableRegistration) { }}%
<span class="header-control"><a fcfEventClick="wrapper.onRegistration()">!{{Registration}}!</a></span>
%{{ } }}%
<span class="header-control"><a fcfEventClick="wrapper.onSingin()">!{{Sign in}}!</a></span>
%{{ } }}%
</div>
<div class="header-controls-line">
@{{ render.template("@controls:language-selector", {fcfClass: "language-selector-header"}); }}@
</div>
</div>
<div class="header-clear"></div>
</div>
<div class="body">
@{{ render.template("+body"); }}@
</div>
</body>
</html>
//~TEMPLATE body
<h4>Main body container</h4>
In the basic framework of the application, the styles file :templates/css/styles.css is connected via the clientInclude option, in the OPTIONS section. The rest of the template settings are left by default.
Now let's move on to the HTML itself to the TEMPLATE section.
The page title is almost entirely rendered programmatically in the @{{}}@ output construct, using the render.header(). The site header is formed depending on the user's rights and application settings.
The page context is rendered in a container div with class body. It renders the "body" sub-template:
<div class="body">
@{{ render.template("+body"); }}@
</div>
The base page template :templates/pages/main-page.tmpl, being inherited from :templates/super/page.tmpl, overrides the content of the body sub-template.
Template content :templates/pages/main-page.tmpl:
//~OPTIONS
{
// Basic inheritance template
// Default: undefined
extends: ":templates/super/page.tmpl",
// 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
// 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: [],
// [Since 1.1.43] DOM elements merge flag.
// If true, then existing items are not replaced when updated, but updated.
// Default: false
merge: false,
// 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,
// 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 body
{
}
//~TEMPLATE body
<center>
<p>!{{Welcome}}!!</p>
<p>!{{To log in, specify the 'root' user and the 'root' password}}!.</p>
<p>!{{Don't forget to change your password}}!. <a href="/fcfpackages/fcfManagement/access">!{{Password change}}!.</a></p>
</center>