This page looks best with JavaScript enabled

Dealing with defaults

 ·  ☕ 8 min read

Wiki admins often want to take a template parameter (for example, {{{name}}} in {{hello|name=James Holden}}) and manipulate it in some way depending on how the user specifies the parameter, or even whether the user specifies the parameter at all.

In this post, I’m going to walk through some use cases and explain how to solve them. There are two extensions you will need installed on your wiki in order to follow along fully:

Types of parameters

First of all, let’s talk about the two types of parameters. They are:

  • Named parameters (like name in {{hello|name=James Holden}})
  • Ordered parameters (like the parameter in {{hello|James Holden}})

A named parameter called name can be accessed via {{{name}}} in the template body (and this is case-sensitive, |Name= will not fill {{{name}}}; and {{{name}}} and {{{Name}}} are different in your template code). Ordered parameters can be accessed via {{{1}}}, {{{2}}}, {{{3}}}, etc.1

When you call (transclude) a template, you can also explicitly send an ordered parameter by naming it with the value of a number, for example {{hello|James Holden}} and {{hello|1=James Holden}} are exactly identical to each other. If you name an ordered parameter like this, you must also name all subsequent ordered parameters. For example:

  • {{hello|Amos Burton|Peaches}} - ok. Amos Burton will be {{{1}}} and Peaches will be {{{2}}}.
  • {{hello|Amos Burton|2=Peaches}} - ok. Amos Burton will be {{{1}}} and Peaches will be {{{2}}}.
  • {{hello|1=Amos Burton|2=Peaches}} - ok. Amos Burton will be {{{1}}} and Peaches will be {{{2}}}.
  • {{hello|2=Amos Burton|Peaches}} - ok. Peaches will be {{{1}}} and Amos Burton will be {{{2}}}.
  • {{hello|1=Amos Burton|Peaches}} - not ok. Peaches will overwrite Amos Burton for {{{1}}}, and {{{2}}} will be empty.
  • {{hello|Amos Burton|1=Peaches}} - not ok. Peaches will overwrite Amos Burton for {{{1}}}, and {{{2}}} will be empty.

Parameter types & whitespace

If you use a named parameter, whitespace will be stripped when your value is sent to the template. In other words, {{Hello|name=James Holden}} is exactly the same as {{Hello|name= James Holden }}. You can also put new lines without any effect, like:

{{Hello|name=

James Holden

}}

However, if you use ordered parameters, whitespace is not stripped. So these are all different from each other:

  • {{Hello|James Holden}}
  • {{Hello|James Holden }}
  • {{Hello| James Holden}}

If you write the number of the parameter you are transcluding, for example, {{Hello|1= James Holden }}, then the ordered parameter acts like a named parameter and strips whitespace.

Try it yourself

  1. On your wiki, create a page called Template:Hello. Write Hello, {{{name}}}! On another page, try writing {{Hello|name=Bobbie Draper}} and preview/save it. What happens?
  2. Try amending the template code (at Template:Hello) to Hello, {{{1}}}!. What happens now? Can you edit the calling code to fix it?
  3. Finally, try the template code Hello, {{{your_name}}}! I'm {{{my_name}}}. Play around with this and try reordering the named parameters to see what happens. What if you change your_name to 1 and my_name to 2? Which version do you think is better? Why?
  4. Ordered parameters seem pretty complicated. Why would you ever want to use them?
Answers
  1. You should see Hello, Bobby Draper!.
  2. If you call the template as {{Hello|name=Bobbie Draper}} you’ll see Hello, {{{1}}}!. We can fix this by writing {{Hello|Bobbie Draper}} (or the not-recommended option {{Hello|1=Bobbie Draper}}).
  3. In this case, we’d rather use named parameters of your_name and my_name, because it would be difficult for the user to remember which is which without names.
  4. If you have a frequently-used template that goes in the middle of paragraph text often, like {{Item|item_name}} which adds an icon to the left of the item name & links to the item’s page, you might want an ordered parameter to make the template easier to use, letting editors type less & not have to remember the name of the parameter.

Default values

A “default” value is a value that gets used when you don’t tell it to be something else. In MediaWiki, you can specify a default value of a parameter using a | symbol, like this:

Hello, {{{your_name|Naomi Nagata}}}! I'm {{{my_name|James Holden}}}.

Here are the possible things you could write, and what happens when you do:

  • If you say {{hello}}, the output will be Hello, Naomi Nagata! I'm James Holden.
  • If you say {{hello|your_name=Rocinante}}, the output will be Hello, Rocinante! I'm James Holden.
  • If you say {{hello|my_name=Rocinante}}, the output will be Hello, Naomi Nagata! I'm Rocinante.
  • And if you say {{hello|your_name=Rocinante|my_name=Canterbury}}, the output will be Hello, Rocinante! I'm Canterbury.

This is very cool, but there is a problem: If you say {{hello|your_name=|my_name=}} then the output will be Hello, ! I'm .

That’s not what we want at all! What’s going on?

The syntax {{{your_name|Naomi Nagata}}} is saying, “if the user doesn’t specify any value for your_name, write Naomi Nagata. Otherwise, write the value that the user specifies.” And if you write {{hello|your_name=}} then you are specifying a value for your_name - an empty string.

An example

Say you have infobox code that looks like this:

{{InfoboxSpaceship
|name=
|volume=
|owner=
|crew=
|faction=
|destroyed=
}}

If destroyed isn’t set, then you want the infobox to automatically say “Never,” otherwise the user specifies a date. You also want to distribute this copyable code to everyone so they know what all the parameters are. But as we just saw this won’t work if you write {{{destroyed|Never}}}!

There are a few ways we can fix this. The first one is to write {{#if:{{{destroyed|}}}|{{{destroyed}}}|Never}}. Now, if destroyed is nonempty, we’ll display that; and otherwise, we’ll display the text Never.

Another way involves ParserPower’s {{#or:}} parser function, which returns the first non-empty argument it comes across. If you have that extension installed,2 you can write {{#or:{{{destroyed|}}}|Never}}. If the user writes |destroyed=2350 then this will return 2350. But if they write |destroyed= and then close out the template, it’ll skip {{{destroyed|}}}, which is an empty string, and move on to display Never.

Try it yourself

  1. What would happen if we wrote {{#or:{{{destroyed}}}|Never}} instead? (In this version, there’s no pipe after destroyed). Why could this be a problem? Can you think of any circumstances in which you’d want this behavior?
  2. Can you rewrite {{#if:{{{destroyed|}}}|{{{destroyed}}}|Never}} using the ifeq parser function? You can check out the ifeq docs. Which version do you like better?
  3. Write your own template that uses either the {{#if:}} construction or the {{#or:}} construction to display content with a fallback. Be creative! If you can’t think of any idea, then try writing a sentence advertising a kitten for adoption, where the user specifies either the color of its fur or “unknown” for the fur color.
Answers
  1. If the user puts |destroyed= then nothing will change, but if they delete the destroyed parameter altogether, the template will output the literal string {{{destroyed}}}. One reason we might want this is if we want to ensure users are correctly using copyable code so we want to show something that looks a lot like an error if they leave out a parameter that should be there.
  2. {{#ifeq:{{{destroyed|}}}||Never|{{{destroyed}}}<!-- end if -->}}.
  3. Here’s an example:
    Cat for adoption!
    * Name: {{{name|}}}
    * Age: {{{age|}}}
    * Fur color: {{#or:{{{fur_color|}}}|Unknown}}
    

Advanced default properties

Depending on your use case, there are some different behaviors you might want out of a parameter. Let’s go through each of them and how you can achieve it. In these examples, our template is called Hello and there’s one parameter called name.

{{Hello}} should… {{Hello|name=}} should… Example code to achieve both requirements
Error Show nothing {{{name}}}
Show nothing Show nothing {{{name|}}}
Show Avasarala Show nothing {{{name|Avasarala}}}
Error Show Avasarala {{#or:{{{name}}}|Avasarala}}
Show nothing Show Avasarala {{#if:{{{name}}}|{{{name|}}}|Avasarala}}
Show Avasarala Show Avasarala {{#or:{{{name|}}}|Avasarala}}
Show Sec General Show Avasarala {{#or:{{{name|Sec General}}}|Avasarala}}

Try it yourself

Try each of these and verify they work. You can go to Template:Hello on your own wiki and preview this:

<includeonly><!-- replace this comment with the parser function code --></includeonly><noinclude>
# v1: {{Hello}}
# v2: {{Hello|name=}}
# v3: {{Hello|name=Chrisjen}}
</noinclude>

Can you rewrite each of the examples that use or: to use if: instead?

Answers
  • {{#or:{{{name}}}|Avasarala}} can be written as {{#if:{{{name}}}|{{{name}}}|Avasarala}}
  • {{#or:{{{name|}}}|Avasarala}} can be written as {{#if:{{{name|}}}|{{{name}}}|Avasarala}}
  • {{#or:{{{name|Sec General}}}|Avasarala}} can be written as {{#if:{{{name}}}|{{{name|Sec General}}}|Avasarala}}

Using switch

You can also achieve all of the above results using the #switch parser function instead of #if and #or. Let’s take a look:

{{Hello}} should {{Hello|name=}} should Example code to achieve both requirements
Error Show Avasarala {{#switch:{{{name}}}|=Avasarala|#default={{{name}}}}}
Show nothing Show Avasarala {{#switch:{{{name}}}|=Avasarala|#default={{{name|}}}}}
Show Avasarala Show Avasarala {{#switch:{{{name|}}}|=Avasarala|#default={{{name|}}}}}
Show Sec General Show Avasarala {{#switch:{{{name}}}|=Avasarala|#default={{{name|Sec General}}}}}

Try it yourself

Try each of these and verify they work. Which version do you prefer, using if/or or always using a switch statement? Why?

Other resources


  1. Yes, MediaWiki is 1-indexed. This may annoy some experienced programmers, but it works out nicely when writing Lua scripts, since Lua is also 1-indexed. However, some parser functions are 0-indexed, for example {{#explode:puppies,kittens|,|1}} will return kittens and not puppies. Always check extension documentation or test it yourself to figure out how it’s indexed. ↩︎

  2. ParserPower is included on all wiki.gg wikis. ↩︎

Share on

river
WRITTEN BY
River
River is a developer most at home in MediaWiki and known for building Leaguepedia. She likes cats.

What's on this Page