Field transclusions have another useful trick up their sleeve: the option to treat the tiddler being transcluded as a template. A template transclusion, like a normal field transclusion, is a means of reusing content, but it allows the tiddler being transcluded to refer to information in the tiddler doing the transclusion.
To return to the metaphor we began back in Slicing Up Content, templates are a sort of lens or optical apparatus with which to look at a tiddler: still nouns themselves, but ones that can be used to modify the way we see other nouns.
Be forewarned that templates are probably somewhat unlike anything you've encountered before, so this section might bend your brain a bit. It's OK if you don't get it the first time around.
The current tiddler
To understand templates, we have to first understand TiddlyWiki's unexpectedly complex concept of the current tiddler. We casually referred to the current tiddler in the Field Transclusions section when talking about the syntax {{!!field}}
, and you probably assumed that the “current” tiddler is the one that you're typing the transclusion into. And in many cases, such as in several of the exercises in that section, it is. But it turns out there's a bit more to it.
An accurate definition of the current tiddler is straightforward: it's just the tiddler that's named in the value of the <<currentTiddler>>
variable. However, the current tiddler is much more interesting than your average variable, because references to this variable are deeply embedded into the syntax and inner workings of TiddlyWiki.
Here are some places you can access the current tiddler:
- Via the
<<currentTiddler>>
variable. - In a field transclusion that does not name any tiddler.
{{!!field}}
refers to thefield
field of the current tiddler, as noted in Field Transclusions. - Via the
all[current]
filter step. - Many widgets assume the tiddler to operate on is the current tiddler unless you say otherwise.
Here are some things that change the current tiddler:
- Transcluding another tiddler with the
{{curly braces}}
syntax. - Using a
$list
widget to enumerate the outputs of a filter (unless you specify otherwise). - Directly setting
currentTiddler
with a$set
or$let
widget. - Using a
$tiddler
widget to change the current tiddler.
For completeness, here are some things that don't change the current tiddler that people often guess would change it:
- Transcluding another tiddler with a
$transclude
widget. - Transcluding another tiddler with the
{{||piped curly braces}}
syntax (this syntax will be described in detail later in the section). - Transcluding the contents of a tiddler as a tab.
When you are looking at a tiddler X
directly in the story river and haven't done anything in that tiddler's wikitext to change the current tiddler, the current tiddler is X
. It's when you start using widgets and transclusions within tiddler X
that it gets complicated – or if the tiddler X
is not displayed directly within the story river but is instead transcluded within another tiddler Y
.
The current tiddler changes when transcluding a tiddler
Let's take a closer look at what happens when we transclude a tiddler. Think back to the first exercise in the Field Transclusions section, the one in which we made Jane's contact information appear on the JaneDoe
tiddler by adding a bunch of transclusions like {{!!email}}
and {{!!family}}
to the JaneDoe
tiddler:
!! Information about Jane
* ''Email'': {{!!email}}
* ''Phone'': {{!!phone}}
* ''Family'': {{!!family}}
* ''Manager'': {{!!manager}}
These field references referred to the JaneDoe
tiddler, since they were in JaneDoe
, we hadn't done anything in the JaneDoe
tiddler to change the current tiddler, and we were looking at the JaneDoe
tiddler directly in the story river at the time.
Easy enough, right? Now let's think about what happens when we transclude Jane's tiddler in another tiddler called AllContacts
. (If you want, you can go try this in your wiki right now.) If we're looking at AllContacts
, we definitely don't want the current tiddler to be AllContacts
while rendering the content of the JaneDoe
tiddler – if it were, we wouldn't be able to see any of Jane's contact information, because we referred to it with, e.g., {{!!phone}}
, and the AllContacts
tiddler doesn't have a phone
field, much less one containing Jane's phone number.
For this reason, anytime we transclude a field of a tiddler using the {{braces syntax}}
, the current tiddler is changed to the tiddler we're transcluding, the contents of the field are processed, and then the current tiddler is changed back. You can imagine that TiddlyWiki does something like this:
<$let currentTiddler="JaneDoe">
{{JaneDoe}}
</$let>
In reality, of course, you don't have to put the $let
widget there yourself, it just happens when you say {{JaneDoe}}
.
When the current tiddler shouldn't change
It gets more complicated, because while resetting the current tiddler like this makes sense as a default and is often exactly what you want, there are other occasions on which it proves unhelpful.
Going back to the exercise, we did a nice job of displaying Jane's contact information on Jane's tiddler…but what about every other contact's tiddler? If we want the contact fields to appear on every contact's tiddler, the most obvious way would be to copy and paste the same list of information and field references to every contact tiddler, but that sounds pretty annoying. This sounds like an ideal place to use transclusion, which lets us include the same content in many different tiddlers without repeating the content.
Let's try this, then: let's excise the “Information about Jane” section we created above from her tiddler (if you've forgotten, there is a button on the editor toolbar to do this, or you can press Ctrl+E). Call the excised tiddler ContactInformationTemplate
, and replace it with a transclusion; {{ContactInformationTemplate}}
should appear in the wikitext of JaneDoe
.
Nice. But wait…none of the information is showing up now. Did you catch why?
Answer
When we transclude the ContactInformationTemplate
into JaneDoe
, the current tiddler is changed to ContactInformationTemplate
, which means we don't have access to the fields on JaneDoe
anymore. We could get around this by changing the transclusions on the ContactInformationTemplate
to look like, e.g., {{JaneDoe!!phone}}
, but then this ContactInformationTemplate
tiddler could only be used with the JaneDoe
tiddler – and being able to reuse the ContactInformationTemplate
tiddler was the entire point of extracting it into a separate tiddler.
Suddenly the behavior that looked nice just a moment ago is exactly what we don't want!
Transcluding a tiddler through a template
To make the ContactInformationTemplate
work the way we want, we need a way of not changing the current tiddler during a field transclusion, or, more generally, making the current tiddler a tiddler of our choice during the transclusion.
This is called transcluding a tiddler through a template. The syntax is {{tiddler||template}}
. So here it would be:
{{JaneDoe||ContactInformationTemplate}}
Add that in the JaneDoe
tiddler in place of plain {{ContactInformationTemplate}}
, and you should immediately see Jane's information show up again, because we told TiddlyWiki to transclude ContactInformationTemplate
, but to make the current tiddler during the transclusion be JaneDoe
, rather than ContactInformationTemplate
. Sweet!
There's a shorter and more flexible way to write this. Just like we can write {{!!field}}
to transclude the field
field of the current tiddler, we can write {{||template}}
to transclude the current tiddler through template
(i.e., not change the current tiddler at all while transcluding template
). So here we can just say:
{{||ContactInformationTemplate}}
In this case, we could also simply use the $transclude
widget, which does not change the current tiddler. The above syntax is equivalent to:
<$transclude $tiddler="ContactInformationTemplate"/>
(If you want to use the $transclude
widget rather than braces but you do want to change the current tiddler, you can set the currentTiddler
variable yourself around the $transclude
widget. The idiomatic way to do this is with the $tiddler
widget, like <$tiddler tiddler="NewCurrentTiddler">
.)
How to think about templates
{{tiddler||template}}
, and the concept of “transcluding a tiddler through a template,” feels backwards to many people at first. This operation actually transcludes the template, giving it access to the fields of the tiddler; our intuitive notion of transcluding a tiddler seems rather to suggest that the tiddler should be transcluded with reference to the information in the template. A good way to read {{tiddler||template}}
is “Put the contents of template right here, but as you're deciding what template looks like, the current tiddler is tiddler, not template.”
It's important to remember that, since everything's a tiddler, a template is not really a thing in itself. That is, unlike in many other similar tools, your TiddlyWiki is not separated into two distinct categories of content, tiddlers and templates. Rather, when you transclude a tiddler through a template, you are using a particular tiddler as a template, to display the content in the other tiddler. A tiddler can be used as a template in one place, and as an ordinary content tiddler with a link to it, or for that matter as a tag, in another. In fact, in many cases, transclusion will have exactly the same effect whether the transcluded tiddler is treated as a template or not. For instance, {{EmployeeProfileSetupMeeting}}
, {{||EmployeeProfileSetupMeeting}}
, and {{JaneDoe||EmployeeProfileSetupMeeting}}
should all do the same thing if you try them: the contents of the EmployeeProfileSetupMeeting
tiddler appears. That's because the EmployeeProfileSetupMeeting
tiddler doesn't contain any references that depend on the current tiddler, such as {{!!field transclusions}}
.
Look out as you move forward: the syntax for templates uses two consecutive pipe characters (||
). In Parameterizing Field Transclusions, we'll see that a single pipe within a field transclusion does something entirely different! (And don't confuse either with a single pipe in a link, which separates the tiddler name or URL from its text.)
When is an error not an error?
When it's displayed on a tiddler you intend to use as a template.
Since templates are usually written expecting the current tiddler to be some other tiddler – not the template tiddler itself – when you look at a template tiddler directly, it may look pretty funny. For instance, there will likely be some data missing. The formatting may even be incorrect, or TiddlyWiki may show an outright error (e.g., a Recursive transclusion error). This should not worry you. In general, the only way to know if a template tiddler is written correctly is to actually use it as a template and see if the expected output appears there.
Exercises
On the current tiddler
In the section on dynamic lists, we used the value of the variable <<currentTiddler>>
, without knowing exactly what it was. Review the use of that variable in the dynamic lists section. What does this usage tell you about the interaction of the current tiddler and the $list
widget?
Modify the MeetingList
so that it does not use the variable reference <<currentTiddler>>
but has identical functionality.
Hint: Try transcluding a field.
go to answerSuppose that in the MeetingList
, we want each meeting to display not only its name, but also the name of the tiddler we're using to look at the information (or, more precisely, the current tiddler as defined by TiddlyWiki). That is, since we're viewing the output in the MeetingList
tiddler, it should say MeetingList
. The list might look something like this:
- An item on MeetingList: EmployeeProfileSetupMeeting
- An item on MeetingList: SecondMeeting
Modify your list widget to achieve this output. The output should continue to be correct if you copy and paste (or transclude) the list widget into a different tiddler – i.e., you cannot simply write MeetingList
literally but must dynamically retrieve the title of the tiddler the list widget is in.
Create a new tiddler called JaneTransclusion
. Transclude the content of the JaneDoe
tiddler here – but without writing the text {{JaneDoe}}
anywhere in the tiddler. Once you do this successfully, find at least one other way to do it. (The answer will show you seven ways that use only tools we've already seen, so there is no shortage of options.)
Tip: If the information about Jane ends up all in one line, try adding some blank lines to your wikitext.
go to answerIn The Finer Points of Procedures, we learned that the scope of a procedure is until the end of the tiddler. But what about when we transclude a tiddler containing a procedure into another tiddler?
go to answerOn templates
Place the ContactInformationTemplate
on all of the contacts in your wiki.
(You may be wondering if there's a way to avoid even the repetition of adding the reference to the template to all your tiddlers. The answer is yes, and we'll be getting there in a couple chapters.)
Our meetings have two fields, at
and participants
, which don't show up anywhere on the meeting tiddlers. Create a new template tiddler, MeetingInformationTemplate
, and add a table something like the following.
| !Time|20200531013141000|
| !Participants|JaneDoe|
Time | 20200531013141000 |
---|---|
Participants | JaneDoe |
Obviously, your version should include the correct information for whichever tiddler the template is being transcluded into. Don't miss the space before the !
in Time
and Participants
in the wikitext, which causes the headings to be right-aligned rather than centered.
Transclude this template at the top of all your meeting tiddlers.
go to answerIn the TicketTrackingLink exercise, we created a procedure that outputs a link to a ticket in the company's ticket-tracking system and placed it in the OnboardingProcess
tiddler. Create a template based on this procedure, called TicketNumberLink
, which displays the link to a project's ticket when it's used as a template for any tiddler that has the ticketnum
field populated. Transclude this template in the text of the OnboardingProcess
project to show its ticket number.
Tip: It may be helpful to get everything working within the OnboardingProcess
tiddler first, then excise the relevant parts into a separate template tiddler – this way, if something doesn't work, you have a better idea of what part isn't right.