DEV Community

Sempare Limited
Sempare Limited

Posted on • Edited on

Accessing data from the Sempare Template Engine for Delphi

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:

  1. Data passed to the template
  2. Data passed upfront in the context
  3. Data queried on demand
  4. Data queried by static helper functions
  5. 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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)