Using the Sempare Template Engine for Delphi

Sempare Limited - Oct 16 - - Dev Community

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.

Here is an overview of what it offers and how to get started.

Key Features

  1. Embedded Logic: You can embed Delphi-like logic directly into your templates, allowing for dynamic content generation based on the variables, records, and functions available in your Delphi project.

  2. Customisable Syntax: The template engine provides a clear and simple syntax, <% %>, to allow easy insertion of variables and expressions. For example, <% var %> will output the content of a Delphi variable directly into the template. This keeps the template code clean and readable. You can change the tags to something else like {{ }} by creating a custom context.

  3. Reusable Templates: You can define reusable template fragments or include other templates within your main template, promoting modular design and easy maintenance. This helps with separating concerns and improving the maintainability of large applications.

  4. Support for Complex Types: The engine supports working with complex types, including arrays, records, classes, which can be queried within the template. The ability to include methods and fields of required types opens up dynamic content handling.

  5. Tailored for Delphi: The engine integrates seamlessly into Delphi, leveraging your existing data structures, making it easy to plug into your existing Delphi applications without extra overhead or learning a completely new framework. The syntax was designed to be pascal-like to make it intuitive and consistent with other Delphi code already being developed.

Example Template

Let’s take a look at a basic example where we generate a simple HTML template with variables and expressions.

type
  TProduct = class
  public
    Name: string;
    Price: Double;
    constructor Create(const AName: string; const APrice: double);
  end;

  TProductsData = TObjectList<TProduct>;

  TTemplateData = class
  end;

  TTemplateData<T:class> = class(TTemplateData)
  protected
    FData: T;
  public
    constructor Create(const AData:T);
    destructor Destroy; override;
    property Data: T read FData;
  end;

[Template('products')]
function TProductController.ListProducts: TTemplateData;
var
  LProducts: TProductsData;
begin
  LProducts:= TProductsData.Create();

  LProducts.Add(TProduct.Create('Laptop', 999.99));
  LProducts.Add(TProduct.Create('Smartphone', 599.99));

  Result := TTemplateData<TProductsData>.Create(LProducts);
end;
Enter fullscreen mode Exit fullscreen mode

Above we have the generic TTemplateData class that has a Data property. This will be referenced by the template. The destructor is present to ensure that Data is disposed of when the class is deallocated.

Corresponding Template (products.tpl)

<h1>Product List</h1>
<ul>
<% for product of Data do %>
  <li><% product.Name %> - $<% product.Price %></li>
<% end %>
</ul>
Enter fullscreen mode Exit fullscreen mode

This example showcases how you can easily loop through a list of products, outputting dynamic content within the template. The for loop allows you to iterate through the list of TProduct objects, and the <% %> syntax is used to display the product’s name and price.

The example above expects the web framework to handle merging the template, the function result, and finally dispose of the memory allocated to the result. To explore how the framework the first thing we need to do is add the unit:

uses
    Sempare.Template;
Enter fullscreen mode Exit fullscreen mode

Now our web framework may have a method such as the following:

procedure Render(const AResponse:TWebServerResponse; const ATemplateName: string; const AData: TObject);
var
   LTemplate : string;
begin
   LTemplate := TFile.ReadAllText(ATemplateName);
   AResponse.Send(Template.Eval(LTemplate, AData));
end;
Enter fullscreen mode Exit fullscreen mode

The above implementation is not very efficient, as this parses the template and then evaluates the template. What we should rather do is parse the template once, and then evaluate the parsed template.

Let us start by breaking it down into two steps to illustrate:

procedure Render(const AResponse:TWebServerResponse; const ATemplateName : string; const AData: TObject);
var
   LTemplate : ITemplate;
begin
   LTemplate := Template.Parse(TFile.ReadAllText(ATemplateName));

   AResponse.Send(Template.Eval(LTemplate, AData));
end;
Enter fullscreen mode Exit fullscreen mode

In the above, we can see that we load the template, parse it into the ITemplate structure, and then evaluate it.

Template Registry

The above code illustrates the simple process of parsing and evaluating templates, but managing templates requires a lot of boilerplate. This is where the Template Registry comes into the picture.

It knows how to load files from disk, embedded resources, and can be customised to also load templates from external sources. By default, the template registry will assume that a 'templates' directory exists relative to the location of the application being run. Further, it can hot-reload templates in DEBUG mode, without the application (e.g. webserver) having to restart.

procedure Render(const AResponse:TWebServerResponse; const ATemplateName : string; const AData: TObject);
begin
   AResponse.Send(Template.Resolve(ATemplateName, AData));
end;
Enter fullscreen mode Exit fullscreen mode

The template registry provides a thread-safe registry, caching the parsed templates, and allowing you to evaluate templates on demand with minimal boilerplate.

Getting Started

From within the Delphi IDE, using the GetIt manager, search for 'Sempare' and click install. This will also give you access to the playground demo application.

Alternatively, it is available on GitHub https://github.com/sempare/sempare-delphi-template-engine

License

The Sempare Template Engine is available under the Apache 2.0 license and the Sempare Commercial License.

Conclusion

The Sempare Template Engine is an ideal choice for Delphi developers looking for a flexible and powerful solution to handle dynamic content generation. Its close integration with Delphi makes it easy to adopt, and its rich feature set provides all the tools necessary to build sophisticated applications.

Whether you’re building a web application or generating reports, the Sempare Template Engine can help simplify your workflow and enhance your project’s maintainability.

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.

. . . . . . . . . . .