Including Other Templates

Fluid has an include statement, but to use it, you have to provide some way for Fluid to find the template you want to include by setting the FileProvider option. This takes anything that implements IFileProvider.

For physical files, you can just set it to an instance of PhysicalFileProvider (this is in the Microsoft.Extensions.FileProviders.Physical Nuget package) and pass in the directory where all your templates are.

TemplateOptions.Default.FileProvider = new PhysicalFileProvider(@"C:\templates");

If you’re pulling your templates from a database or any other method, you will need to write your own provider which implements IFileProvider.

Once this is set, you can include subtemplates:

{% include "other_template" %}

This will look a file called for other_template.liquid in your templates root folder (the .liquid extension is automatically added – this appears to be hard-coded inside the library (right here) and cannot be changed).

(The filename wasn’t case-sensitive on my Windows machine, but that’s likely just due to the underlying OS not being case-sensitive. I imagine it depends on your OS and your file provider.)

Note that you have to pass a quoted string. If you don’t quote the string, Fluid will assume you’re passing a variable as an argument, which you can also do:

{% assign template = "other_template" %}
{% include template %}

Include pathing works down through subdirectories (this is also likely dependent on file provider, but PhysicalFileProvider allows this, at least).

{% include "some/path/to/a/file" %}

Template inclusion is recursive. If A includes B, B can also include C. There is some protection against infinite recursion. (See the MaxRecursion option.) If you do a circular include (A includes B which also includes A), you’ll get an InvalidOperationExeception:

The maximum level of recursion has been reached. Your script must have a cyclic include statement.

Included templates are executed in the same context as their “parent,” they have access to all the same data as the parent.

My name is
{% assign name = "Deane" %}
{% include "B" %}
{{ name }}
My name is
Deane

You can pass variables into included templates by specifying named arguments in the include command.

{% include "B", animal: "Cat" %}

The variable animal will be set in B’s scope.

This syntax works as well.

{% include "B" with "Cat" as animal %}

This is not the same as setting a variable before the include. The difference is in which scope the variable is set.

Consider:

{{ assign animal = "Cat" }}
{% include "B", animal: "Dog" %}
{{ animal }}

For animal, Template A will will see “Cat” even below the include, while Template B will see “Dog.”

  • One method says, “Set animal in Template A’s scope, then include Template B.”
  • The other method says, “Include Template B, and set animal in its scope.”

You can include another template multiple times for all values in a collection. Assume people is a collection of 10 objects.

{% include 'B' for people as person  %}

Template B will be executed 10 times, and each time person will be a successive value from the people collection.