The Sempare Template Engine (available at https://github.com/sempare/sempare-delphi-template-engine and GetIt) is a versatile templating system designed specifically for Delphi developers to streamline the creation and management of dynamic HTML, text, or any other text-based output formats. Whether you are building web applications, reports, or email templates, the Sempare Template Engine offers a powerful yet straightforward solution that integrates with minimal boilerplate into Delphi projects. The template engine has been around since 2019 and has many features for you to explore.
In this tutorial we will explore the various ways in which data can be accessed by Sempare Template Engine templates.
Overview
The template engine provides numerous ways for data to be accessed:
- Data passed to the template
- Data passed upfront in the context
- Data queried on demand
- Data queried by static helper functions
- Data queried by helper methods
This tutorial assumes you have installed the template engine following the instructions discussed elsewhere.
Let us explore each of these approaches.
Data passed to the template
This is the simplest approach where we pass data while evaluating the template.
program test;
uses
Sempare.Template;
type
TTemplateData = record
Name : string;
end;
var
LData: TTemplateData;
LTemplate : ITemplate;
begin
LData.Name := 'Joe';
LTemplate := Template.Parse('Hello <% name %>');
writeln(Template.Eval(LTemplate, LData));
end;
Data passed upfront in the context
By default, the Template helper methods will create a new context if you do not provide one. A context allows us to provide bespoke configuration that changes the way the template engine behaves. We can use this to also store global variables.
program test;
uses
Sempare.Template;
var
LContext: ITemplateContext;
LTemplate : ITemplate;
begin
LContext := Template.Context();
LContext.Variable['Company'] := 'Sempare Limited';
LContext.Variable['CopyrightYear'] := 2024;
LTemplate := Template.Parse('Copyright <% Company %>, <% CopyrightYear %>');
writeln(Template.Eval(LContext, LTemplate, LData));
end;
Data queried on demand
Rather than injecting values into the context, we can provide an anonymous function that allows for values to be resolved.
program test;
uses
Sempare.Template;
var
LContext: ITemplateContext;
LTemplate : ITemplate;
begin
LContext := Template.Context();
LContext.VariableResolver := function(const AContext: ITemplateContext; const AName: string; out AResult: TValue): boolean
begin
if AName = 'Company' then
begin
AResult := 'Sempare Limited';
exit(true);
end;
if AName = 'CopyrightYear' then
begin
AResult := 2024;
exit(true);
end;
AResult := '';
exit(false);
end;
LTemplate := Template.Parse('Copyright <% Company %>, <% CopyrightYear %>');
writeln(Template.Eval(LContext, LTemplate, LData));
end;
Above, the resolver must return true if it is able to find the result. The AResult is a TValue from the RTTI unit which can store anything.
Note that if you allocate memory, you must deallocate memory yourself after the template has been evaluated.
Data queried by static helper functions
program test;
uses
Sempare.Template;
type
THelperMethods = class
class function GetCompany() : string; static;
class function GetCopyrightYear() : integer; static;
end;
class function THelperMethods.GetCompany() : string;
begin
exit('Sempare Limited');
end;
class function THelperMethods.GetCopyrightYear() : integer;
begin
exit(2024);
end;
var
LContext: ITemplateContext;
LTemplate : ITemplate;
begin
LContext := Template.Context();
LContext.Functions.AddFunctions(THelperMethods);
LTemplate := Template.Parse('Copyright <% GetCompany() %>, <% GetCopyrightYear() %>');
writeln(Template.Eval(LContext, LTemplate, LData));
end;
In the above, we have illustrated how we add static functions and procedures.
Data queried by helper methods
program test;
uses
Sempare.Template;
type
TCompanyInfo = class
function GetCompany() : string;
function GetCopyrightYear() : integer;
property Company: string read GetCompany;
property CopyrightYear: integer read GetCopyrightYear;
end;
function TCompanyInfo.GetCompany() : string;
begin
exit('Sempare Limited');
end;
function TCompanyInfo.GetCopyrightYear() : integer;
begin
exit(2024);
end;
var
LCompanyInfo : TCompanyInfo;
LContext: ITemplateContext;
LTemplate : ITemplate;
begin
LCompanyInfo := TCompanyInfo.Create;
try
LContext := Template.Context();
LContext.Variables['company'] := LCompanyInfo;
LTemplate := Template.Parse('Copyright <% _.Company %>, <% _.CopyrightYear %>');
writeln(Template.Eval(LContext, LTemplate, LData));
finally
LCompanyInfo.Free;
end;
end;
In the above, we also use '_' which is a magic variable that is an alias for the data being passed into the template.
Conclusion
As we have seen above, the Sempare Template Engine is very flexible and allows you to access data in many ways, allowing you to use it according to your usage pattern.
Sponsorship Required
Please help us maintain the project by supporting Sempare via GitHub sponsors (https://github.com/sponsors/sempare) or via our payment link (https://buy.stripe.com/aEU7t61N88pffQIdQQ). Sponsors can obtain access to our integrated IDE wizard for RAD Studio.