Developer log #18 :: Flexform instances

Instances can be used to store template calls within a parameter of another template. In source code this ends up looking like the following example, where "Hours worked" is the parameter that contains "Hours spent" template calls:
{{Log
|Person=Liselot Roelen
|Date=2022-07-15
|Hours worked={{Hours spent
|Hours spent on=Task/275
|Hours=1
}}{{Hours spent
|Hours spent on=Task/296
|Hours=0.25
}}{{Hours spent
|Hours spent on=Task/297
|Hours=4.5
}}
}}
FlexForm-logo square.png

When to use instances

Instances are used when you want to store items to a page, with additional data for each individual item. For example if you wanted to store a list of speakers at an event, you could simply use a token field. However if you want to store additional information, such as the start and end time for each speaker, it would make sense to use instances. In this case you might use the following form:
{{Event
|Date=2022-09-02
|Speakers={{Speaker at event
|Name=Liselot
|Start=14:00
|End=14:30
}}{{Speaker at event
|Name=Charly
}}
}}

<_form action="addToWiki">

<_edit target="{{PAGEID}}" template="Event" formfield="Speakers" />

<_instance 
template-parent="Event" 
template="Speaker at event" 
name="Speakers" 
>
<div>
<_input type="text" name="Name" placeholder="Name" />
<_input type="text" name="Start" placeholder="Start" />
<_input type="text" name="End" placeholder="End" />
</div>
</_instance>

<_input type="submit" value="Save" />

</_form>
You can copy paste this example and try it out on your own wiki. This should give you a functioning form that will edit the page it's on. It should look like the image below:

Flexform-instances-demo.png

Note that the Event template is intentionally a nonexisting template to keep this example simple. FlexForm will be able to edit the page regardless. After saving you can view the source code to see the changes.

Using default-content

FlexForm will automatically fill the instances with values currently in the source code. If the source code does not have these values, for example because you are using instances in a form for creating a new page, you can use the "default-content" parameter to fill the instances with default values. For example you might use this to have default start and end times so you will only have to fill the names when creating a new event page. You could use the following source code to do this:

{{Event
|Date=2022-09-02
}}

<_form action="addToWiki">

<_edit target="{{PAGEID}}" template="Event" formfield="Speakers" />
<_instance 
template-parent="Event" 
template="Speaker at event" 
name="Speakers" 
default-content="{{Instance default content}}"
>
<div>
<_input type="text" name="Name" placeholder="Name" />
<_input type="text" name="Start" placeholder="Start" />
<_input type="text" name="End" placeholder="End" />
</div>
</_instance>

<_input type="submit" value="Save" />

</_form>

Note that this example requires you to create an additional template, "Template:Instance default content", with the following source code:

<nowiki>{{Speaker at event
|Start=10:00
|End=10:45
}}{{Speaker at event
|Start=11:00
|End=11:45
}}{{Speaker at event
|Start=12:00
|End=12:45
}}{{Speaker at event
|Start=13:00
|End=13:45
}}</nowiki>

It is necessary to wrap the template calls in a nowiki tag, because FlexForm parses the default-content. This is done because sometimes in more complicated cases you want to query default values from other pages, so you'll have some parts of the default-content in nowiki tags and others not.

Sometimes default-content is also used with template calls without parameters, just to make sure there is already an instance visible on the page without the user having to click the "+" button.

Other use cases

These are some more examples where we have used instances:

  • Logging hours worked (with worker, project, time spent and description) and commute distance (with worker, distance and vehicle), with the option to specify default commute values for each person.
  • Checklists of tasks that need to be performed on specific dates. Checklists can be added to individual pages. Through using Semantic MediaWiki subobjects and querying you can also create a complete overview of all unfinished tasks across the wiki.
  • Orders with products, where in each instance you can fill in a product, price, amount and more. The data can then be used for example to generate an invoice document.
Lua error: bad argument #1 to 'mw.text.jsonDecode' (string expected, got nil).