DEV Community

Sempare Limited
Sempare Limited

Posted on • Edited on

1

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.

Hot sauce if you're wrong - web dev trivia for staff engineers

Hot sauce if you're wrong · web dev trivia for staff engineers (Chris vs Jeremy, Leet Heat S1.E4)

  • Shipping Fast: Test your knowledge of deployment strategies and techniques
  • Authentication: Prove you know your OAuth from your JWT
  • CSS: Demonstrate your styling expertise under pressure
  • Acronyms: Decode the alphabet soup of web development
  • Accessibility: Show your commitment to building for everyone

Contestants must answer rapid-fire questions across the full stack of modern web development. Get it right, earn points. Get it wrong? The spice level goes up!

Watch Video 🌶️🔥

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️