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 article, we will explore how a FireDAC TDataSet can be enumerated from a Sempare Template Engine template.
The code for this tutorial is available at https://github.com/sempare/sempare-devto-examples/tree/dev/FireDACInMemory
Creating a mock dataset
We normally get a TDataSet back from a database query. In this tutorial, I'll construct a TFDMemTable which we can use later in a template.
function CreateMockUsersTable(): TFDMemTable;
procedure AddPerson(const AName: string; const AAge, AWeight: integer);
begin
result.Append;
result.FieldByName('name').value := AName;
result.FieldByName('age').value := AAge;
result.FieldByName('weight').value := AWeight;
result.Post;
end;
begin
result := TFDMemTable.Create(nil);
result.FieldDefs.Add('name', ftWideString, 20);
result.FieldDefs.Add('age', ftInteger);
result.FieldDefs.Add('weight', ftFloat);
result.CreateDataSet;
AddPerson('joe', 20, 67);
AddPerson('pete', 19, 87);
AddPerson('jane', 23, 47);
end;
In the function above, we create a TFDMemTable containing 3 users. We first define the fields and then add the users.
templates/users.tpl
<h1>Users</h1>
<% for idx in Users %>
<tr>
<td><% idx %></td>
<td><% Users.name %></td>
<td><% Users.age %></td>
<td><% Users.weight %></td>
</tr>
<% onbegin %>
<table>
<tr>
<th>No</th>
<th>Name</th>
<th>Age</th>
<th>Width</th>
</tr>
<% onend %>
</table>
<% onempty %>
<div>There are no users</div>
<% end %>
In the above template, we use some of the additional 'events' on loops to control various aspects around when the header, body and footer is created, as well as what to output when there is no data. During each iteration, the the loop will dereference the various fields from the dataset, as we see with 'Users.name' as an example.
Now to pull it all together:
program FireDACInMemoryExample;
uses
Data.DB,
FireDAC.Comp.Client,
System.SysUtils,
Sempare.Template;
function CreateMockUsersTable(): TFDMemTable;
begin
// code from above
end;
type
TTemplateData = record
Users: TDataSet;
end;
var
LTemplateData : TTemplateData;
begin
LTemplateData.Users := CreateMockUsersTable;
try
writeln(Template.Resolve('users.tpl', LTemplateData));
finally
LTemplateData.Users.Free;
end;
end.
This will give us a simple HTML table:
<h1>Users</h1>
<table>
<tr>
<th>No</th>
<th>Name</th>
<th>Age</th>
<th>Width</th>
</tr>
<tr>
<td>1</td>
<td>joe</td>
<td>20</td>
<td>67</td>
</tr>
<tr>
<td>2</td>
<td>pete</td>
<td>19</td>
<td>87</td>
</tr>
<tr>
<td>3</td>
<td>jane</td>
<td>23</td>
<td>47</td>
</tr>
</table>
Gotchas
Something to be aware of. When enumerating using the for statement, the index variable returns an offset into the data set, starting from 1.
We dereference fields directory off the dataset as shown above. If there are spaces in the field name, you can use array dereferencing style. e.g. In the above Users.name and Users['name'] are equivalent.
Conclusion
The above example has illustrated how a simple HTML report can be generated with an in memory FireDAC table.
The Sempare Template Engine is very flexible, configurable and extensible, allowing for a good seperation of concerns between your business logic that will access data, and the templating engine that will render/present your data as required.
The template engine is available on https://github.com/sempare/sempare-delphi-template-engine and via Embarcadero GetIt.
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.