Skip to content

Frond (Twig) Templates

TIP

TTina4Twig is a Twig-compatible template engine for server-side rendering, supporting variables, control structures, filters, functions, template inheritance, and macros.

Basic Usage

pascal
var
  Twig: TTina4Twig;
  Variables: TStringDict;
begin
  Twig := TTina4Twig.Create('C:\templates');
  Variables := TStringDict.Create;
  try
    Variables.Add('name', 'Andre');
    Variables.Add('items', TValue.From<TArray<String>>(['Apple', 'Banana', 'Cherry']));

    Memo1.Lines.Text := Twig.Render('hello.html', Variables);
  finally
    Variables.Free;
    Twig.Free;
  end;
end;

Variables

Output variables with double curly braces:

{{ name }}
{{ user.email }}

Setting Variables

{% set greeting = 'Hello' %}
{% set items = ['Apple', 'Banana'] %}
{% set total = price * quantity %}

Control Structures

if / elseif / else

{% if users|length > 0 %}
  <ul>
    {% for user in users %}
      <li>{{ user.name }}</li>
    {% endfor %}
  </ul>
{% elseif guests|length > 0 %}
  <p>Guests only</p>
{% else %}
  <p>No users found</p>
{% endif %}

for loops

{% for item in items %}
  <p>{{ item }}</p>
{% endfor %}

{% for key, value in pairs %}
  <p>{{ key }}: {{ value }}</p>
{% endfor %}

{% for i in 0..10 %}
  <p>{{ i }}</p>
{% endfor %}

with

Scopes variables to a block:

{% with { title: 'Hello' } %}
  <h1>{{ title }}</h1>
{% endwith %}

Template Inheritance

extends and block

base.html:

<html>
<head><title>{% block title %}Default{% endblock %}</title></head>
<body>
  {% block content %}{% endblock %}
</body>
</html>

page.html:

{% extends 'base.html' %}

{% block title %}My Page{% endblock %}

{% block content %}
  <h1>Hello World</h1>
{% endblock %}

include

{% include 'header.html' %}
{% include 'sidebar.html' with { menu: items } %}

Set the template path so includes resolve correctly:

pascal
Twig := TTina4Twig.Create('C:\MyApp\templates');

Macros

Define reusable template fragments:

{% macro input(name, value, type) %}
  <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ input('username', '', 'text') }}
{{ input('password', '', 'password') }}

Filters

Filters transform values using the pipe | operator. They can be chained:

{{ name|upper|length }}

String Filters

FilterDescriptionExample
upperUppercase<span v-pre>{{ 'hello'|upper }}</span>HELLO
lowerLowercase<span v-pre>{{ 'HELLO'|lower }}</span>hello
capitalizeCapitalize first letter<span v-pre>{{ 'hello'|capitalize }}</span>Hello
titleTitle case<span v-pre>{{ 'hello world'|title }}</span>Hello World
trimRemove whitespace<span v-pre>{{ ' hi '|trim }}</span>hi
nl2brNewlines to <br><span v-pre>{{ text|nl2br }}</span>
striptagsRemove HTML tags<span v-pre>{{ html|striptags }}</span>
replaceReplace values<span v-pre>{{ 'hello'|replace({'e': 'a'}) }}</span>
splitSplit into array<span v-pre>{{ 'a,b,c'|split(',') }}</span>
slugURL-friendly slug<span v-pre>{{ 'Hello World'|slug }}</span>hello-world
spacelessRemove whitespace between tags<span v-pre>{{ html|spaceless }}</span>
uUnicode string<span v-pre>{{ text|u }}</span>

Number Filters

FilterDescriptionExample
absAbsolute value<span v-pre>{{ -5|abs }}</span>5
number_formatFormat number<span v-pre>{{ 1234.5|number_format(2, '.', ',') }}</span>
format_numberFormat with decimals<span v-pre>{{ 1234|format_number }}</span>
format_currencyFormat as currency<span v-pre>{{ 1234|format_currency('USD') }}</span>

Array Filters

FilterDescriptionExample
lengthLength of array/string<span v-pre>{{ items|length }}</span>
firstFirst element<span v-pre>{{ items|first }}</span>
lastLast element<span v-pre>{{ items|last }}</span>
joinJoin into string<span v-pre>{{ items|join(', ') }}</span>
keysGet array keys<span v-pre>{{ obj|keys }}</span>
mergeMerge arrays<span v-pre>{{ arr1|merge(arr2) }}</span>
sortSort array<span v-pre>{{ items|sort }}</span>
reverseReverse array/string<span v-pre>{{ items|reverse }}</span>
shuffleRandomize order<span v-pre>{{ items|shuffle }}</span>
sliceExtract portion<span v-pre>{{ items|slice(1, 3) }}</span>
batchSplit into chunks<span v-pre>{{ items|batch(3) }}</span>
columnExtract column<span v-pre>{{ users|column('name') }}</span>
filterFilter with callback<span v-pre>{{ items|filter }}</span>
findFind value<span v-pre>{{ items|find }}</span>
mapMap with callback<span v-pre>{{ items|map }}</span>
reduceReduce to single value<span v-pre>{{ items|reduce }}</span>
minMinimum value<span v-pre>{{ items|min }}</span>
maxMaximum value<span v-pre>{{ items|max }}</span>

Date Filters

FilterDescriptionExample
dateFormat date<span v-pre>{{ post.created|date('Y-m-d') }}</span>
date_modifyModify date<span v-pre>{{ date|date_modify('+1 day') }}</span>
format_dateFormat date (alias)<span v-pre>{{ date|format_date }}</span>
format_datetimeFormat datetime (alias)<span v-pre>{{ date|format_datetime }}</span>
format_timeFormat time<span v-pre>{{ date|format_time }}</span>

Date format uses PHP-style specifiers that are automatically converted:

SpecifierMeaningExample
Y4-digit year2026
y2-digit year26
mMonth (zero-padded)03
nMonth (no padding)3
dDay (zero-padded)01
jDay (no padding)1
HHour 24h (zero-padded)14
hHour 12h (zero-padded)02
iMinutes30
sSeconds05
AAM/PMPM
DShort day nameMon
lFull day nameMonday
MShort month nameJan
FFull month nameJanuary

Encoding Filters

FilterDescriptionExample
escape / eEscape HTML entities<span v-pre>{{ html|escape }}</span>
rawNo escaping<span v-pre>{{ html|raw }}</span>
url_encodeURL encode<span v-pre>{{ text|url_encode }}</span>
json_encodeEncode to JSON<span v-pre>{{ data|json_encode }}</span>
json_decodeDecode from JSON<span v-pre>{{ json|json_decode }}</span>
convert_encodingConvert charset<span v-pre>{{ text|convert_encoding('UTF-8') }}</span>
data_uriCreate data URI<span v-pre>{{ content|data_uri }}</span>

Other Filters

FilterDescription
defaultFallback value: <span v-pre>{{ name|default('Guest') }}</span>
formatString formatting: <span v-pre>{{ 'Hi %s'|format(name) }}</span>
pluralPlural form
singularSingular form

Functions

FunctionDescriptionExample
rangeGenerate number/letter sequence{% for i in range(1, 10) %}
dumpDebug output<span v-pre>{{ dump(variable) }}</span>
dateCreate/format dates<span v-pre>{{ date('now', 'Y-m-d') }}</span>

Operators

CategoryOperators
Comparison==, !=, <, >, <=, >=
Logicaland, or, not
String~ (concatenation), in, starts with, ends with, matches
Math+, -, *, /, %, **
Range.. (e.g., 1..10, 'a'..'z')

Integration with TTina4HTMLRender

The HTML renderer has built-in Twig support via its Twig property:

pascal
Tina4HTMLRender1.SetTwigVariable('title', 'Hello');
Tina4HTMLRender1.Twig.Text := '<h1>{{ title }}</h1>';

See HTML Renderer - Twig Integration for details.

Sponsored with 🩵 by Code InfinityCode Infinity