Template Variables Explained

If you migrated an existing IntraWeb application from an older version (e.g. Delphi Seattle on IW14) to a modern release (Delphi 13 on IW16) and use TIWTemplateProcessorHTML with custom HTML templates, you may have run into a case where a tag like {%scriptSearchSubjekt%} placed inside a <script> block is silently ignored — even though the exact same template worked fine before.

This is not a bug. It’s a deliberate change in how the template parser behaves starting with IntraWeb 16.2.2, and there’s a clean, supported replacement: Template Variables.

 

What changed

In IW14 and earlier 16.x builds, TIWTemplateProcessorHTML would scan the entire template file — including the contents of <script> tags — looking for {%TagName%} markers and replacing them with control HTML or custom values.

Starting with IW 16.2.2, the template parser no longer parses or modifies JavaScript. Tags inside <script> blocks are left untouched.

The reasoning behind the change is straightforward: JavaScript is a full programming language, not a markup language. The template parser was written to understand HTML structure — tags, attributes, nesting — not JavaScript syntax (strings, template literals, comments, regex, etc.). Trying to safely find-and-replace inside arbitrary JS using an HTML-aware parser is fragile by construction; it’s easy to construct valid JavaScript that a naive text substitution would mangle (for example, a tag name that happens to appear inside a string literal or a comment). Removing that capability closes off a class of subtle rendering bugs, at the cost of breaking templates that relied on the old behavior.

This lines up with IntraWeb’s broader parser philosophy: the HTML template parser is intentionally simple and fast, and defers anything that isn’t plain HTML structure to other mechanisms rather than trying to be a general-purpose parser for every language that might be embedded in a page.

The supported replacement: Template Variables

Template Variables were introduced as a first-class IntraWeb feature (added in IW 15.5.4, as part of the broader “Template Variables feature, simplifies template development” additions in the IW15 line). They exist precisely to cover the use case of injecting dynamic values into places — including inside <script> blocks — where the HTML-aware parser won’t (and shouldn’t) touch.

The key distinction: replacing a variable is a pure search-and-replace operation, not a parse operation. The processor is not trying to understand JavaScript syntax at all — it just swaps the literal tag text for a literal value string. That’s exactly why it’s safe to use inside <script> tags: there’s no HTML/JS structural analysis involved, so there’s nothing about JavaScript syntax that could confuse it.

Another practical detail worth keeping in mind: template variable names are matched case-sensitively. `{%scriptSearchSubjekt%}`, `{%ScriptSearchSubjekt%}` and `{%SCRIPTSEARCHSUBJEKT%}` are treated as three distinct variables, not as the same one. Use consistent casing in both the code and the template. Why case-sensitive rather than case-insensitive? Templates are processed on every render, so performance matters, and a case-sensitive search is the most efficient way to match variable names, avoiding the extra overhead that case normalization or case-insensitive comparison would add on every pass.

That safety comes with one responsibility shifted to the developer: since there’s no parsing or validation, you need to make sure the variable name doesn’t collide with anything else in the page (other tags, other variables, literal text that happens to match the pattern) across the HTML, CSS, and JS in the template.

Option 1- Fixed value at design time

Set the value directly on the Variables property of TIWTemplateProcessorHTML, e.g.:

VariableName=VariableValue

This is the simplest option, but it’s static – functionally not very different from hardcoding the value straight into the template itself. Useful mainly for values that never change across sessions or deployments.

Option 2 – Runtime value, set per instance

Set the variable’s value in a form-level event such as OnCreate or OnRender:

procedure TForm1.IWAppFormCreate(Sender: TObject);
begin
  IWTemplateProcessorHTML1.Variables.Values['VariableName'] := 'VariableValue';
end;

This gives full flexibility to compute the value from business logic, session state, or user context. Using OnRender instead of OnCreate means the value can change between renderings of the same form instance — for example, if the user triggers a refresh, they can get a different value without a new form being created.

Option 3 – Runtime value via OnGetVariableValue

Instead of pushing the value proactively, you can leave the variable’s value empty and let the template processor pull it lazily via the OnGetVariableValue event:

procedure TForm1.IWTemplateProcessorHTML1GetVariableValue(Sender: TObject;
  const Name: string; var Value: string);
begin
  if SameStr(Name, 'VariableName') then
    Value := 'VariableValue';
end;

Important detail: this event only fires when the variable’s configured value is empty. If a value has already been set on the Variables property, the event is skipped for that variable. The event fires once per distinct variable found in the template, so if the same template contains several different variables, expect the handler to be called multiple times: always check variable’s Name before assigning Value.

Migration checklist

If you’re upgrading a template-based IW14/older-IW16 app that embeds {%tag%} markers inside <script> blocks, here’s the practical path:

  • Identify every tag reference that sits inside a <script>...</script> block in your templates.
  • Create a new template variable with the same name, in the template processor component.
  • Pick the setting strategy per variable: fixed value, OnCreate/OnRender assignment, or OnGetVariableValue — based on whether the value is static, session-dependent, or needs to change between re-renders.
  • Double-check variable names don’t collide with other tags, other variables, or literal text elsewhere in the page — since there’s no parser catching conflicts for you anymore.
  • Re-test the rendered output in the browser to confirm the value lands where expected inside the script block.

System Variables

Alongside the user-defined variables described above, TIWTemplateProcessorHTML also recognizes a fixed set of system variables. These are replaced automatically wherever they appear in the template source — inside HTML, JavaScript, or CSS alike — without any configuration required on your part.

The supported system variables are: WWWROOT, APPURLBASE, CACHEURLBASE, USERCACHEURLBASE, INTERNALURLBASE, APPURL, NONCE, APPNAME, and APPDISPLAYNAME.

Remember that all these variable names are also case-sensitive, so they must appear all in uppercase in your template, e.g: 

Welcome to {%APPDISPLAYNAME%}

Takeaway

Tags inside <script> blocks stopped being processed by TIWTemplateProcessorHTML from IW 16.2.2 onward because JavaScript can’t be safely parsed and rewritten by an HTML-focused parser. Template Variables — introduced as a dedicated IntraWeb feature — are the supported way to inject dynamic values into any part of a template, script blocks included, precisely because variable substitution is a plain text replacement rather than a parse-and-modify operation. The tradeoff is that avoiding naming collisions becomes the developer’s responsibility rather than the parser’s.

Scroll to Top