8.4.3 Template inheritance
The goal of this feature is to be able to split of the common layout of multiple pages to one shared base template, to avoid repetition.
Disclaimer: this feature borrowed quite some ideas from Django's template language.
126.96.36.199 Basic terminology
- base template: the template that defines the skeleton page structure (the general page layout) with regions to be filled by the child templates
- child template: a template which inherits from a base template
- the child template extends the base template
- multiple levels of inheritance are possible, so a template can at the same time be a child template and a base template
188.8.131.52.1 The basics
184.108.40.206.1.1 The base template
The base template is a template that contains t:block elements to define regions that can be overridden by child templates.
.... <t:block name="content"> [ default content for when block is not overridden] </t:block> ...
220.127.116.11.1.2 The child template
A child template is a template with on the root element a t:inherit attribute. The value of the t:inherit attribute is the URI of the base template. This attribute is evaluated at runtime, so it can contain expressions to dynamically determine the base template.
The child template can contain t:block elements to replace the t:block elements with the same name from the base template.
All content outside of the blocks will not be used.
It is not an error to have blocks which do not exist in the base template, these will be ignored.
It is not required for a child template to define all the blocks from the base template. If a block is not overridden, the block-content from the base template will be outputted.
The t:block start tag and end tag themselve are never outputted, only the content of the block is outputted.
The child template can have html, body, and other tags which facilitate viewing or editing the child template as an individual page.
Each block has its own scope: variables defined within the block will not be visible to other blocks.
<html t:extends="base.html"> <t:block name="content"> .... </t:block> <t:block name="navigation"> <t:superBlock/> </t:block> </html>
18.104.22.168.2 Calling the block from the base template: t:superBlock
When overriding a block, it might be that you want to keep the content from the block in the base template, and only add to it.
This is possible using the t:superBlock element.
Suppose this base template:
<html> <t:block name="foo"> base template content </t:block> </html>
And this child template:
<html> <t:block name="foo"> Hello world. This is the content from the base template: <p><t:superBlock/></p> </t:block> </html>
Will produce this output:
<html> Hello world. This is the content from the base template: <p>base template content</p> </html>
As this example illustrates, the <t:superBlock/> element can be located at any position and depth within the overriding block.
22.214.171.124.3 Cross-block initialization: t:init
Suppose you have a child template with a few blocks:
<html> <t:block name="block1"> ... </t:block> <t:block name="block2"> ... </t:block> <t:block name="block3"> ... </t:block> </html>
Remember that only the content of the t:block elements from the child template is executed. Often, you will run in the situation that you want to define some variables and macro's to use in multiple of these blocks. This is possible by defining them in a t:init element.
<html> <t:init> <t:variable name="foo" value="bar"/> </t:init> <t:block name="block1"> ... </t:block> <t:block name="block2"> ... </t:block> <t:block name="block3"> ... </t:block> </html>
When executing a template that uses inheritance, the template engine will first execute the t:init blocks from each of the templates, starting with those from the top-level base template. This allows child templates to redefine variables and macro's defined by the base templates.
The t:init element can contain any template instructions, but will be executed in silent mode, which means it will produce no output. Typically it will contain variables and macro's, but it can for example be useful to conditionally define a variable using t:if .
If one template file contains multiple t:init elements, they will simply all be exeucted.
- What happens with init blocks from included and imported templates? Probably executed when executed the included template.
- What happens when an included or imported template itself inherits from base templates? Probably this simply works as expected.