Extension:Page Forms/Defining forms

From mediawiki.org

Page Forms provides an entire syntax for defining forms, that makes use of tags contained within triple curly brackets. Pages that contain such syntax should always go in the "Form:" namespace (or, for non-English-language wikis, its equivalent in another language). Such pages are not called forms, but rather "form-definition pages", to distinguish them from the actual corresponding forms that users see.

It is recommended that, when starting out with Page Forms, you should not try creating form-definition pages from scratch, but rather use one of Page Forms' helper pages to create them: Special:CreateClass or Special:CreateForm - or copy from some other example, or use the Page Schemas extension. Later on, to make changes to the form, you will most likely have to edit the form definition directly, unless you make use of Page Schemas; in either case, the following documentation should be helpful.

Form markup language[edit]

Forms are defined using a set of tags that specify templates and fields within those templates. Wikitext, and some HTML, can be freely embedded anywhere outside of the tags. The allowed tags are:

'info' tag[edit]

The info tag holds special information about the form. This tag is optional, but should be placed at the top of the form if it is present. Allowed parameters of this tag are:

create title=title Sets the title for the 'FormEdit' page, if the form is being used to create a new page. By default, the page name will appear right after this title; however, you can embed the page name within the title by putting "<page name>" within the title value.
edit title=title Sets the title for the 'FormEdit' page, if the form is being used to edit an existing page. You can similarly embed "<page name>" within this title value.
query title=title Sets the title for the 'RunQuery' page
page name=formula Sets a formula for automatic setting of the name of the page being added; see "Linking to forms#The one-step process".
query form at top Places the form at the top, instead of the bottom, for the 'RunQuery' page
onlyinclude free text Indicates that the free text in the page generated by the form should be placed within an "<onlyinclude>" tag, so that pages created by the form can be transcluded in other pages without affecting those other pages' semantic properties.

'for template' tag[edit]

The for template tag specifies a template name, and declares that all of the following fields (until end template is reached) will be those of this template. The name immediately following the for template declaration is the name of the template. Allowed parameters of this tag are:

label=label text Specifies a label to be placed in a square around the entire set of this template's fields in the form. This is especially useful if the template can have multiple instances.
multiple Specifies that the user can change the number of instances of this template in the form, allowing multiple (or zero) occurrences; see "Multiple-instance templates", below.
intro= Sets text that is placed before the inputs of this template. This is especially useful for multiple-instance templates with a "label" set, but can be used for any template.
display= Sets a pre-set display for all the inputs for this template; the wikitext around the input tags (if any) will simply be ignored. This parameter can take three values: "table" (which can be used for any template), "spreadsheet" (which can be used only for multiple-instance templates) and "calendar" (which can be used only for multiple-instance templates that contain at least one date field). In all three cases, the field name serves as the "label" of each input, unless a "label=" value is specified for that input. See "Spreadsheet-style editing" for more information on the "spreadsheet" option.
height= Sets the height for the "spreadsheet" display; default is 200px.
minimum instances=number For multiple-instance templates, sets the minimum number of allowed instances.
maximum instances=number For multiple-instance templates, sets the maximum number of allowed instances.
add button text=text For multiple-instance templates, sets the text in the "Add another" button.
strict Specifies that only fields in the form that correspond to fields used by the template should get turned into form elements.
embed in field=template name[field name] Used for embedded templates; see Embedded templates.
displayed fields when minimized=field names Specifies the comma separated field names to be displayed on instances when collapsed to a bar; see "Multiple-instance templates", below.

'end template' tag[edit]

The end template tag ends the range of a template. There are no parameters for this tag.

'field' tag[edit]

The field tag specifies a field to be placed in a form, corresponding to a template field. The name immediately following the field declaration is the name of the template field. There are a large variety of possible parameters to this tag, some of which can only be used for certain input types.

Parameters that can be applied to any field are:

input type=input type Specifies the type of input this field will have in the form. If a field corresponds to an SMW property or Cargo field, the form will usually have the correct input type by default; otherwise the default is text. If the corresponding SMW property, or Cargo field, cannot be automatically determined, you can use the parameter "property", or the parameters "cargo table" and "cargo field", to manually specify it (see below). The allowed set of input types is different for every SMW or Cargo type; see "Input types" for the full list of options.
hidden Specifies that this field will be hidden in the form: used to preserve values in edited pages.
mandatory Specifies that this field must be filled in by the user. Note: mandatory should not be used in conjunction with hidden. Use of both in any field will cause the mandatory check on any field to fail when the form is saved.
restricted Specifies that this field will be editable only by admins/sysops and disabled for all other users. This parameter can also be called as "restricted=group name", which restricts editing of the field to the specified user group.
default=default value Specifies a default value for this field. This default only takes effect when creating a new page, not when editing existing pages. For date-related fields, default=now will set the value to the current date and possibly time. For text fields, default=current user will set the value to the username of the user adding this page, and default=uuid will set the value to a random universally unique identifier. For the checkbox input type, default=yes will check the checkbox by default. (The "checkboxes" input type, on the other hand, like the "listbox" type, requires specifying the actual values, like default=Value A, Value C.) You can also include templates, parser functions, and magic words within the "default=" value.
class=class name Specifies a CSS class that the input for this field should have.
property=property name Specifies that the field corresponds to a certain Semantic MediaWiki property, and should thus get the corresponding input type, autocompletion, etc.
cargo table=table name and cargo field=field name Collectively used to specify that this form field corresponds to a certain Cargo field, and should thus get the corresponding input type, autocompletion, etc.
cargo where=where clause Corresponds to the "where=" parameter for Cargo queries; used to limit the set of allowed or autocompleted values when using data from a Cargo field.
list Specifies that this field contains a list of values.
delimiter=delimiter Specifies the delimiter character or string this field should use, if it represents a list of values; the default is ",".
label=label text If a "display=" value is set in the for templatetag, this parameter sets the name of the label for this field (by default, the label is the name of the field).
label msg=label message Instead of label text, sets the name of a message (defined at a page in the "MediaWiki:" namespace) to be inserted, to allow for translation.
feeds to map=template name[coordinates field name] Can be applied to more than one field, to specify that these set of fields collectively define an address that should be used to locate a set of coordinates.
holds template Used for embedded templates; see Embedded templates.
translatable If the Translate extension is installed, specifies that Translate tags that look like "<!--T:X-->" should be wrapped around the value of this input.
unique Specifies that the value entered for this field must be unique, i.e. must not be the same as any value for the SMW property (if SMW is being used) or Cargo field (if Cargo is being used) corresponding to this template field.
unique for category=category name Specifies that the value entered for this field must not be the same as the name of any page in the given category.
unique for namespace=namespace name Specifies that the value entered for this field must not be the same as the name of any page in the given namespace.
unique for concept=concept name Specifies that the value entered for this field must not be the same as the name of any page in the given SMW "concept".
  • The following parameters are input type-specific:
    • allow half stars, autogrow, cols, default filename, depth, description, editor, existing values only, height, hide select all, hideroot, image, image preview, include timezone, label, mapping cargo table, mapping property, mapping template, mapping using translate, max height, max values, maxlength, namespace, num stars, placeholder, rows, show on select, show select all, size, star width, starting bounds, structure, top category, uploadable, values, values from category, values from concept, values from external data, values from namespace, values from property, values from url, width

You can find more information about these input type-specific parameters, and in general for form fields, on the Input types page.

'section' tag[edit]

The section tag specifies a textarea to be placed in a form, that corresponds to a page section. The name immediately following "section|" is the name of the section. Allowed parameters of this tag are:

level=level Specifies the "level" of the section heading; can be 1-6, corresponding to '=' through '======' in wiki markup. See "Sections" for more information.
hide if empty Specifies that the section header should not get added to the page at all if the section is empty.

The following parameters, which can also be used for the "textarea" input type and the free text input, can also be used for sections. See "The free text input" section below.

  • mandatory
  • restricted
  • hidden
  • class
  • placeholder
  • rows
  • cols
  • autogrow

'standard input' tag[edit]

The standard input tag is used for ten different inputs that usually appear at the bottom of every form. The text immediately after standard input| is the name of each input. The most notable of these inputs is 'free text', which is a textarea that holds all the non-template, non-section text in a page. The other nine are form elements such as the "Save" and "Preview" buttons; see Defining the bottom of the form for the full list.

The 'free text' input has more elaborate handling than the other standard inputs; see below for its allowed parameters.

For the other standard input types, the allowed parameters are:

label=label name Specifies the text associated with this input on the form.
class=CSS class(es) Specifies the CSS class for this input.
style=CSS rule(s) Specifies the CSS style for this input.

In addition, the 'watch' input type can take in the parameter 'checked', which checks the "Watch this page" checkbox by default.

The free text input[edit]

The "free text" input sets a textarea that holds all the non-template, non-section text in a page. The following parameters for "textarea" fields can also be used for free text inputs:

  • rows
  • cols
  • hidden
  • restricted
  • default
  • class
  • autogrow
  • editor

In addition, there is one parameter available only for the "free text" input - "preload":

  • preload=page title - Specifies a page whose contents should be preloaded into this field.

If it is left out of the form definition, any free text in a page will be preserved in the form as a hidden field, not viewable or modifiable by the user.

Caching[edit]

You can have the set of values used for autocompletion in forms be cached, which may improve performance. To do that, add something like the following to LocalSettings.php:

$wgPageFormsCacheAutocompleteValues = true;
$wgPageFormsAutocompleteCacheTimeout = 60 * 60 * 24; // 1 day (in seconds)

The timeout value is in seconds; it can take any number.

Multiple values for the same field[edit]

Page Forms supports having multiple values within a given field, and some form input types - like "checkboxes" and "listbox" - are specifically geared for fields that contain multiple values. Text and textarea fields can also support autocompletion for multiple values. If a form field is meant to hold multiple values, the corresponding template field should most likely contain a call to either #arraymap or #arraymaptemplate - see "Page Forms and templates#Multiple values for the same field". Regardless of what is contained in the template, though, the fact that a field is meant to hold multiple values can be hard-coded in the form definition by adding the parameter "list" to the {{{field}}} tag. The parameter "delimiter=" can also be helpful, if the delimiter between values is meant to be something other than the default (a comma).

The default input type for a field with multiple values is "tokens".

Multiple-instance templates[edit]

If you add the 'multiple' parameter to a template, it will allow for multiple (or no) instances of this template in the form, and therefore in the generated page. The sample form below, for the 'Item' form, contains two such templates. If you look at the form that this definition generates, you can see that there are two buttons labeled "Add another". Clicking on either of these will create a new instance of that template and its field(s). Instances can be rearranged, by clicking on the icon on the right-hand side and dragging the instance up or down within the set.

You can rename the "Add another" button to any other text, using the "add button text=" parameter. For instance, to change the button to read "Add another occupation" for a template called "Occupation", you could have "{{{for template|Occupation|multiple|add button text=Add another occupation}}}".

You can set the minimum and maximum number of instances users can set for such a template, using the "minimum instances=" and "maximum instances=" parameters, respectively.

To avoid overloading the screen, in a displayed form, if the height of all the instances together (in pixels) is greater than the value defined for $wgPageFormsHeightForMinimizingInstances (which by default is 800), then all the instances get "minimized", with each one turned into a bar that then expands into the full instance when clicked on. You can change this height value in LocalSettings.php to whatever number of pixels you want. Or, if you want to disable minimizing altogether, just set it to a negative number, like -1. To name the collapsed bar with field names, use displayed fields when minimized=; see 'for template' tag, above.

If you want to semantically store all the data contained in these multiple-instance templates, then, if you are using the Cargo extension, the standard storage will work fine; but if you are using Semantic MediaWiki, the template should make use of a call to #subobject instead of regular property settings. (And make sure that the subobject is not named, so that it gets an automatically-assigned name.) An example call, for a template that contains the fields "Start date" and "End date", would be:

{{#subobject:|Has start date={{{Start date|}}}|Has end date={{{End date|}}}

Embedded templates[edit]

You can choose to have all instances of a multiple-instance template be stored as the value of a parameter for some other template, so that the calls to that template will not look like:

{{Skill|Name=Cooking|Level=5}}
{{Skill|Name=Guitar|Level=2}}
{{Skill|Name=Karate|Level=4}}

...but instead like:

{{Person
...
|Skills={{Skill|Name=Cooking|Level=5}}{{Skill|Name=Guitar|Level=2}}{{Skill|Name=Karate|Level=4}}
...
}}

In order to accomplish this example, you would just need to:

  • Add a tag like "{{{field|Skills|holds template}}}" within the "Person" template part of the form definition
  • Add "{{{Skills|}}}" somewhere inside the page Template:Person, so that it gets displayed in pages
  • Add "|embed in field=Person[Skills]" to the "{{{for template|Skill|multiple" part of the form definition

There are several advantages to this approach:

  • You have much greater control over where the multiple-instance template goes, in both the form and the resulting pages - so you can have it placed between any two fields in the "main" template.
  • You can easily place special text before and after the multiple-instance template, like a table header and footer, without the need for special header and/or footer templates.
  • No spaces get placed between calls to the template, which may potentially help with formatting.

Note that you cannot embed multiple-instance templates inside other (regular or embedded) multiple-instance templates.

An example of using multiple-instance templates with "holds template" and "embed in field" can be found here.

Spreadsheet-style editing[edit]

You can have spreadsheet-style editing of a multiple-instance template, using the Jspreadsheet library. Every template call is displayed as one row in the "spreadsheet". To do that, just add "|display=spreadsheet" to the "for template" tag. The wikitext between the "for template" and "end template" tags will get ignored for this display; only the "field" tags are handled.

With spreadsheet-style editing, the input type= parameter for fields is handled differently. The default is text, and possible alternate values are textarea, checkbox and date. If any set of possible values is defined for this field, the display will be a dropdown.

You can also set the height of the display using the height= parameter; the default is 200px.

An example of Spreadsheet-style editing can be found here

Calendar-based editing[edit]

With "display=calendar", you can create and edit template calls that contain one or more date/datetime fields, using a calendar interface, via the FullCalendar library. Each template call represents one event.

With calendar editing, selecting or creating an event brings up a popup form to edit the event's fields. The popup form handles the standard input types except for combobox, googlemaps, leaflet and openlayers.

You can set the field which holds the title of the event through the "event title field" parameter of the "for template" tag. If events in this calendar have only one date, "event date field" should be used. On the other hand, if events have both start and end dates, "event start date field" and "event end date field" should be used.

event title field=field name(text) Specifies the field that hold the title of the event.
event date field=field name(date/datetime) Specifies the field that hold the date of the event for single-date events.
event start date field=field name(date/datetime) For multiple-instance templates, specifies the field that hold the start date of the event for two-date events.
event end date field=field name(date/datetime) For multiple-instance templates, sspecifies the field that hold the end date of the event for two-date events.

Defining the bottom of the form[edit]

The user inputs at the bottom of the form can be customized using the "standard input" tag. The layout, inclusion and text of each input can be modified. Each user input is defined as a "standard input" tag with its own value; the allowed values are:

  • "save" (for the "Save page" button)
  • "preview" (for the "Show preview" button)
  • "save and continue" (for the "Save and continue" button - this lets users save the page without leaving the form)
  • "changes" (for the "Show changes" button)
  • "summary" (for the "Summary" text field)
  • "minor edit" (for the "This is a minor edit" checkbox)
  • "watch" (for the "Watch this page" checkbox)
  • "cancel" (for the "Cancel" link)
  • "run query" (for the "Run query" button in query forms)

So, for example, the button for "Save page" could be specified with "{{{standard input|save|label=Save this page}}}", which would place the button where it was defined, with the text on the button reading "Save this page". If no standard input tags are included in the form definition, the basic seven inputs ("save", "preview", "changes", "summary", "minor edit", "watch" and "cancel") will appear at the bottom of the form, just as they do for regular "Edit" pages. However, if even one such tag is included, then only those inputs which have been included will be displayed, in the order, and with the wiki-text, that they appear in in the form definition.

Sample form[edit]

Here is the source code for the 'Item' form definition page at Discourse DB:

{{{info|add title=Add an opinion item|edit title=Edit an opinion item}}}
<div id="wikiPreview" style="display: none; padding-bottom: 25px; margin-bottom: 25px; border-bottom: 1px solid #AAAAAA;"></div>
{{{for template|Item}}}
{| class="formtable"
! Author:
| {{{field|author|mandatory}}}
|-
! Source:
| {{{field|source|mandatory}}}
|-
! Date:
| {{{field|date}}}
|-
! URL:
| {{{field|url}}}
|-
! Quote:
| {{{field|quote|input type=textarea}}}
|}
{{{end template}}}

{{{for template|Opinion|label=Opinions for this item|multiple}}}
'''Topic:''' {{{field|1}}}

'''Position:''' {{{field|2|size=55}}}

'''Stance:''' {{{field|3|size=10}}}
{{{end template}}}

{{{for template|Reference|label=Previous opinion items this item refers to|multiple}}}
'''Item name:''' {{{field|1|values from category=Items}}}
{{{end template}}}

'''Free text:'''

{{{standard input|free text}}}

Note the presence of both wiki-text and some limited HTML (the 'div' tag) within the code. This markup is based around the templates Item, Opinion and Reference. You can see the working form at this add data page; the form itself is created on-the-fly from the form definition file. In the 'Items' category page, if you click on any of the pages, you can see the 'edit with form' tab on the top right-hand side. If you click on that tab, you can see this same form, this time populated with the data contained in that page.

The 'wikiPreview' div tag, by the way, is included so that, when the user hits the "Preview" button, they'll be shown the preview directly within the form page, instead of being taken to another page. It is not necessary, and can be safely removed from any form definition.

The #forminput function[edit]

Form-definition pages generated by Page Forms (i.e., by Special:CreateForm or Special:CreateClass) always include a call to the #forminput function, which provides an input for users to reach that form.

  1. forminput is not actually a part of the form-definition syntax, though.

For information on how to modify the #forminput call, see Linking to forms#The two-step process.

Other topics[edit]

Turning forms into tabbed sections[edit]

If you think a form is too long for users to fill out comfortably, you can turn it into sections, with a tab interface to navigate between them, using the Header Tabs extension. If you install this extension, it is very easy to add tabs to a form: just add a top-level section wherever you want a tab to appear, of the form "=Tab 1="; and then add the tag "<headertabs/>" near the bottom of the form, right above the "standard input" declarations. You can place tab declarations between templates, or within templates, to split up the fields of a template into different tabs. You can see a simple example of a form in tabbed sections here; the form definition used to create it is here.

Such tabs can also be used, in a similar way, to display data pages themselves.

Wizard-style display[edit]

Another approach to dealing with a large form is to give it a wizard-style interface, which is similar to having tabs but more sequential, in that users are supposed to go in order from the first screen to the last, with each screen containing some number of form inputs. This can especially be useful when there is a lot of explanation required for the different inputs. To have a wizard-style interface, just put HTML tags that look like <div class="pf-wizard-screen"> around each successive group of inputs that are meant to go together. The following would define three screens, for example, with the third holding a "Save" button:

<div class="pf-wizard-screen">
Field 1: {{{field|Field 1}}} <br />
Field 2: {{{field|Field 2}}} <br />
Field 3: {{{field|Field 3}}}
</div>
<div class="pf-wizard-screen">
Field 4: {{{field|Field 4}}} <br />
Field 5: {{{field|Field 5}}} <br />
Field 6: {{{field|Field 6}}}
</div>
<div class="pf-wizard-screen">
{{{standard input|save}}}
</div>

Note that, if you are giving a form a wizard-style display, every part of the form should be part of some "pf-wizard-screen" div.

Reusing form elements[edit]

If you have a set of forms that all contain the same text or sections, you can avoid duplication by creating templates that are used within those forms. Simply place all the text that you want repeated within a template, and call that template within each form. If that template contains form elements (like field definitions), the characters within the form elements simply need to be HTML-escaped - replace '{' with '&#123;', '|' with '&#124;' and '}' with '&#125;'. Or just use <nowiki> around them.

Caching form definitions[edit]

When a form is displayed, the form definition is parsed twice - first to turn the wiki-text into HTML, and then to handle the SF-specific tags like "{{{field}}}". If a form on your wiki takes a long time to display, it might be due to the first parse, which has been known to take seconds to run. You can have form definitions be cached, so the (mostly) HTML version can be retrieved directly, eliminating the first parse. To do this, add the following line to LocalSettings.php:

$wgPageFormsCacheFormDefinitions = true;

$wgPageFormsFormCacheType is set to null by default. If left at null, the parser cache will be used for caching. If set to one of the possible cache types (e.g. CACHE_ANYTHING), the selected cache will be used. This way it is possible to switch off the parser cache (e.g. to force re-evaluation of queries on every page load) and still cache the (rarely changed) form definitions.

$wgPageFormsFormCacheType = CACHE_ANYTHING;

Note: if any of your form definitions contain any elements that do dynamic display, such as {{PAGENAME}} or {{CURRENTUSER}}, these will not get displayed correctly if forms are cached, so you shouldn't use caching.

Tooltips[edit]

You can add tooltips to your form in three different ways:

  • If you have the Semantic MediaWiki extension installed, you can use the #info parser function defined by Semantic MediaWiki, e.g., {{#info:tooltip text}}. (This parser function is not to be confused with Page Form's "{{{info}}}" tag.) See Help:Adding tooltips for more help.
  • Use the #tip-info parser function, defined by the SimpleTooltip extension.
  • If you have "display=table" specified within a "{{{for template}}}" tag, you can add a "tooltip=" parameter for any field in that template.