Chapter 17 Page Forms
You have created infobox templates to handle all your data, and thought of ideal page layouts for every scenario. But how do you get the users to use any of what you've created? That's where the Page Forms extension comes in: it lets you define forms that can be used to create and edit pages using the structure you have set up. It makes use of information, such as field types, from Cargo and/or Semantic MediaWiki whenever possible, in an attempt to make creating the forms as easy as possible.
Getting started
The rest of this chapter provides a breakdown of the syntax and workflows you can use with Page Forms. But if you're just getting started, the best approach is to use Page Forms' helper pages to quickly create pages. There are essentially five good options:
- Use the page Special:CreateClass to create everything at once – categories, templates and forms.
- Use the individual pages Special:CreateCategory, Special:CreateTemplate and Special:CreateForm to create the entire data structure. This is a more hands-on approach, which is less ideal for starting out, but it's quite useful if you already have templates and categories in place (and possibly properties as well), and only want to create what is still missing.
- Similar to the previous option, you can go to any specific not-yet-created category, template or form page, and click on the “create with form” tab, which displays a form that matches the form found in the relevant one of those four special pages.
- Copy from an existing installation or package. If you see a data structure setup that you like elsewhere, you can copy and paste all the necessary files to your wiki. (Though it's usually a good idea to get their permission first, even if legally it probably isn't necessary.) And there may be a package of such pages, created with a generic purpose like project management in mind, that you want to copy onto your wiki; a few companies offer such packages.
- Use the Page Schemas extension. See here for an introduction to this extension; it lets you create a set of “schemas” for your data structure, from which forms, templates etc. can be automatically generated.
First, let's look at Special:CreateClass. Figure 17 shows the interface that appears on that page.
Using this interface, you can define an entire “class” – a data structure to represent a single page type, which is composed of a template, a form, a category, and properties. Not every page type can be defined in this way – some pages will contain more than one standard template, for instance – but in many cases it's a good starting point. The set of fields at the bottom is used to create the template, the form, and the properties.
Why bother creating the category? Because, in Page Forms, the category is where the connection between pages and their forms is defined, so that an “edit with form” tab shows up at the top of each page. This is done via the #default_form function, which we'll get to later.
Another option is to use the special pages Special:CreateCategory, Special:CreateTemplate and Special:CreateForm, all defined by Page Forms. These have the advantage of granularity – you can create, or regenerate, any specific pages – and they also have the advantage of additional fields that Special:CreateClass doesn't offer.
For example, in Figure 17 you can see part of the helper form at Special:CreateForm – it lets you set all the allowed parameters for each form field, with the group of parameters based on the selected input type. We'll get to all of these specific parameters in the next section.
Form definitions
Page Forms provides an entire syntax for defining forms, that makes use of special tags contained within triple curly brackets. Pages that define forms 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.
Before we define the syntax, here's an example of the full contents of a form-definition page, for a “Project” form:
This is the 'Project' form.To add a site with this form, enter its name below;if a page with that name already exists, you will be sent to a form to edit that page.{{#forminput:form=Project|autocomplete on category=Projects}}</noinclude><includeonly><div id="wikiPreview" style="display: none; padding-bottom: 25px; margin-bottom: 25px; border-bottom: 1px solid #AAAAAA;"></div>{{{for template|Project}}}{| class="formtable"! Client| {{{field|Client|input type=combobox|values from category=Clients}}}|-! Start date| {{{field|Start date}}}|-! End date| {{{field|Start date}}}|-! Status| {{{field|Status}}}|}{{{end template}}}{{{for template|Task|multiple|label=Tasks}}}{| class="formtable"! Task name| {{{field|Task name}}}|-! Deadline| {{{field|Deadline}}}|-! Status| {{{field|Status}}}|}{{{end template}}}</includeonly>
Already, without getting into any of the specifics of the syntax, you can notice a few things:
- The form-definition page serves a dual purpose: within the <includeonly> tag it holds the form definition, while within the <noinclude> tag it holds a brief explanation of that form, and an input to get to the actual form. (These two tags, <includeonly> and <noinclude>, serve the same purpose that they do in templates – see here.)
- Form definitions hold a mix of regular wikitext and special syntax, the latter of which is defined within three curly brackets.
- A form can specify more than one template within a page – in this case, there are two.
- Form fields, for the most part, can be simple, although they can also take in parameters. (Form field tags tend to be simple because Page Forms can already get a lot of information about the nature of each field from its template.)
We'll get to a full explanation later of almost all the elements of this definition, but one thing that won't be covered later is the <div id="wikiPreview"> element. That is there so that, when the user hits the “Show preview” button, the Page Forms code can display both the form and the previewed page on the screen at the same time. It's an optional element.
You can see what this form page looks like when a user goes there in Figure 17. Only the top part of the page's contents, within the <noinclude> tag, is displayed.
When they reach the input on the form definition page, the user has to enter a page name. Let's say that they enter the text “Planting flower garden” and press “Create or edit”. Figure 17 shows what the resulting form page, defined by the “Project” form definition, would look like in action (after the user also presses the “Add another” button once).
It's very important to note that this form can be used to both create new pages and edit existing ones; the form will look the same in both cases, other than having its values pre-populated for existing pages.
Now, let's go through the form-definition syntax.
Form markup language
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. Page Forms tags are always surrounded by three curly braces, have pipes to separate their “parameters”, and usually contain at least one extra parameter, to define the name. The text “{{{field|Start date}}}” from the previously-shown form definition is a PF tag, for instance. They differ from template calls because they have three curly brackets instead of two. And they differ from parameters within template definitions, which have three curly brackets, because those can only be used in the “Template:” namespace, whereas PF tags can only be used within the “Form:” namespace.
Below is a listing of the allowed tags in form definitions, and the allowed parameters for each. It may be helpful to refer back to the sample form definition on here, to see how these tags can fit in context.
'info' tag
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.
- edit title=title – Sets the title for the 'FormEdit' page, if the form is being used to edit an existing page.
- 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 "The one-step process".
- query form at top – Places the form at the top, instead of the bottom, for the 'RunQuery' page.
'for template' tag
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 text immediately following the 'for template' declaration is the name of the template. Allowed parameters of this tag are:
- label= – 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", on here.
- 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.
- 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= – 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= – Used for embedded templates; see here.
'end template' tag
The 'end template' tag ends the range of a template. There are no parameters for this tag.
'field' tag
The 'field' tag specifies a field to be placed in a form, corresponding to a template field. The text 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 a semantic property, the form will usually have the correct input type by default; otherwise the default is text. If the corresponding semantic property cannot be automatically determined (e.g. if it's in a template being called indirectly), you can use the parameter “property” to manually specify it (see below). The allowed set of input types is different for every semantic property type; see here 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.
- 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. 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. 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 appropriate 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.
- 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 ",".
- holds template – Used for embedded templates; see here.
- 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".
For all input type-specific parameters, and a lot more information about configuring form fields, see the upcoming “Input types” section.
'section' tag
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. For the most part, this tag takes in all the same parameters that the textarea input type can take in - see page 17. There are two additional parameters:
- level= - takes in a number from 1 to 6, specifying the level of the section heading.
- hide if empty - Specifies that the section header should not get added to the page at all if the section is empty.
'standard input' tag
The 'standard input' tag is used for nine 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 text in a page. The other seven are form elements such as the "Save" and "Preview" buttons; see here for the full list. The 'free text' input has more elaborate handling than the other standard inputs; see “The free text input” 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=label name – Specifies the CSS class for this input.
- style=label name – 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.
Input types
The input types
text
The default input type; corresponds to the HTML "text" input.
Special parameters:
- size=size – Specifies the width of the input, in characters.
- maxlength=maximum length – Specifies the maximum allowed length of the input.
- placeholder=placeholder text – Specifies help text that is displayed in the input until the user clicks on it.
textarea
Corresponds to the HTML <textarea> tag.
Special parameters:
- rows=num rows – Specifies the number of rows.
- cols=num cols – Specifies the number of columns.
- maxlength=maximum length – Specifies the maximum allowed length of the input.
- autogrow – Sets the textarea to "auto-grow" its height to match that of its contents, so that a scrollbar won't be needed.
- editor=editor type – Adds a JavaScript-based editor to the textarea to make editing its contents more user-friendly. The following values are supported:
- max height=maximum height - If VisualEditor is being used, specifies a maximum height (in pixels) for the textarea, since VE uses autogrow. By default, this value is 400 px.
- placeholder=placeholder text – Specifies help text that is displayed in the input until the user clicks on it.
rating
This input type displays a star rating, as usually used for reviews.
Special parameters:
- num stars= - the number of stars; default is 5.
- allow half stars - allow the user to select half a star, for ratings like 3.5.
combobox
The "combobox" input type provides a combo box interface: an input that functions like a regular autocomplete field, but has an additional down-arrow icon, like that of a dropdown, to let the user see all the available values at once.
Special parameters:
- size= - Specifies the width of the input, in characters.
- existing values only - Disallows arbitrary values in the field.
- placeholder= - Specifies help text that is displayed in the input until the user clicks on it.
tokens
This input type "tokenizes" the values in the field, i.e puts a block around each value to make it a single unit instead of just a string of characters. These "tokens" can then also be rearranged.
Special parameters:
- size= - Specifies the width of the input, in characters.
- max values= - Specifies the maximum number of allowed values.
- existing values only - Disallows arbitrary values in the field.
- placeholder= - Specifies help text that is displayed in the input until the user clicks on it.
radiobutton
The "radiobutton" input corresponds to the HTML "radio" input. It shows a set of values from which the user can only choose one.
By default, the first radiobutton value is "None", which lets the user choose a blank value. To prevent "None" from showing up, you must make the field "mandatory", as well as making one of the allowed values the field's "default=" value.
dropdown
The "dropdown" input corresponds to the HTML <select> tag. It shows a dropdown list of values, from which the user can only choose one.
checkboxes
The "checkboxes" input displays checkboxes to let the user choose any number of values.
listbox
The "listbox" input corresponds to the HTML <select> tag, with the "multiple" attribute added. It shows a vertical list of options, where the user can select any number of values.
Special parameters:
- size= - Specifies the height of the listbox.
tree
The "tree" input type allows for a hierarchical, tree-style input, where all the values have either radiobuttons or checkboxes next to them, depending on whether the field can hold one item or many. Values can either come from a category tree within the wiki, or be set manually within the form definition.
How does this input know whether it can hold one or multiple values, and should thus display radiobuttons vs. checkboxes? It checks whether the field in the template is defined as holding a list of values (using #arraymap) or not. This check is not perfect, though. If the tree input is showing radiobuttons instead of checkboxes, you just need to add the parameter "|list" to the field tag in the form definition, to establish that this is a list.
Depending on the source of the values, you need to specify one of these two additional parameters:
- top category= - sets the name of the category at the top of the "tree".
- structure= - sets the entire tree structure; should use wikitext-style bullets to set the depth level.
If you use the "structure" parameter, it should look something like this:
{{{field|Location|input type=tree|structure=*Universe**Milky Way Galaxy***Solar system**Andromeda Galaxy...etc.}}}
You can also optionally set these parameters:
- height= - sets the height, in pixels, of the box in which the tree appears.
- width= - sets the width, in pixels, of the box in which the tree appears.
- delimiter= - sets the delimiter when the field can hold a list of values. Default is ','.
- hideroot - hides the name of the top category.
- depth= - sets the number of levels of the three that are shown at the beginning. Default is 10.
If you're using the "tree" input type to display a category tree, note that this input will print out only the names of the categories selected, without the "Category:" namespace before it; so if you want that to show up in the page as well, the template will have to add it.
If the field specifies multiple categories, and the template uses #arraymap to do it, the call to #arraymap should look something like:
{{#arraymap:{{{Categories|}}}|,|x|[[Category:x]] |<nowiki> </nowiki>}}
...in other words, you need to specify the final "delimiter" parameter for #arraymap, and make it a space, blank or something similar, to avoid printing commas between the category tags.
checkbox
A single checkbox, used for boolean values.
date
This input contains three separate entries, for the year, month and day.
datetime
The "datetime" input is similar to the "date" input, but includes additional entries for hours, minutes, seconds and AM/PM.
Special parameters:
- include timezone - specifies that a time zone entry should also be included.
year
"year" is a simple text input that is used to get a year-only value for a date field.
datepicker, datetimepicker
"datepicker" lets the user pick a date with the help of a JavaScript-based popup calendar. “datetimepicker” extends the datepicker input by also including a popup input for the time. Both of these inputs have many optional parameters, but most likely you will not need to use any of them.
googlemaps, leaflet, openlayers
The "googlemaps", "leaflet" and "openlayers" input types let you display a map to get a coordinate value, using the Google Maps, Leaflet or OpenLayers services, respectively.
You can also optionally set these parameters for these input types:
- height= - sets the height, in pixels, of the map.
- width= - sets the width, in pixels, of the map.
- starting bounds= - takes in a pair of coordinates to set the bounds of the map displayed; this parameter only applies if the input does not have a value. (Example value for this parameter: "-20,-15;50,55".)
- image= - available only for the “leaflet” input type; sets an image (must be an image that has been uploaded to the wiki) to be the background of the map, instead of a standard map of the world.
regexp
The "regexp" input type is not a true input type, but rather the ability to display another input (most often "text") with additional, regular-expression-based validation.
Special parameters:
- base type - The base type to be used. May be any input type that generates an HTML form element of type input or select (e.g. text (with or without values), listbox, dropdown, etc.). Defaults to text.
- base prefix - Prefix for the parameters of the base type (see example)
- regexp - The regular expression the input has to match to be valid. This value must include the slashes! It defaults to /.*/, i.e. any value.
Allowed input types for data types
Each defined Semantic MediaWiki or Cargo data type has a default input type, and, when applicable, a default input size as well. Additionally, some data types have special handling if the field holds a delimited list of values, instead of just a single value.
Here are the defaults and the other allowed input types for each data type, for single values:
Data type
|
Default input type
|
Other allowed input types
|
Page
|
combobox
|
text, textarea, tree
|
String
|
text
|
combobox, textarea, tree
|
Text
|
textarea
|
text
|
URL
|
text
|
textarea
|
Integer, Float
|
text
|
textarea
|
Date, Start date, End date
|
date
|
datepicker, year (simply a text input)
|
Datetime, Start datetime, End datetime
|
datetime
|
datetimepicker
|
Enumeration
|
dropdown
|
radiobutton
|
Boolean
|
checkbox
|
dropdown, radiobutton
|
Coordinates
|
openlayers
|
googlemaps, leaflet
|
And here are the default and other allowed input types for delimited lists of a certain data type:
Data type
|
Default input type
|
Other allowed input types
|
Page
|
tokens
|
text, textarea
|
String
|
text
|
tokens, textarea
|
Enumeration
|
checkboxes
|
listbox
|
Hierarchy
|
N/A
|
tree
|
Setting values and mappings
For inputs that have a predetermined set of values, whether they are hardcoded (like the "dropdown" input) or suggested (like "combobox"), the values must be defined somewhere. If you are using SMW or Cargo, these values may already be defined outside the form. However, you can always override them within the form - or set them for a field that otherwise has no values defined for it. Here are some of the parameters that can be used in the "field" tag:
- values=possible values - Specifies a set of either possible values or autocompletion values (depending on the input type) that this field can have, overriding whatever set of values may have been set from Semantic MediaWiki or Cargo. This set of values is separated by commas by default, but the delimiter can be modified using the delimiter= parameter.
- values from category=category name - Similar to values=, but gets its values from the names of all pages belonging to a specific category.
- values from namespace=namespace name - Similar to values=, but gets its values from the names of all pages belonging to a specific namespace. (To get values from the main namespace, use "Main" for the namespace name, or just leave it blank.)
- values from wikidata=Wikidata query string - takes in one or more pairs of Wikidata properties and items, and finds all matching values; an example string would be P31=Q5398426&P136=Q1786567 (instance of = TV series, genre = medical drama)
There are several more options for the autocompletion-based inputs; see the next subsection, "Autocompletion".
You can also set "mappings", if you want the set of values displayed to the user to be different from the set of values that actually show up in the page's wikitext. The following parameters enable such mappings:
- mapping template=template name - Takes in the name of a "mapping template" (a template that takes in a single, unnamed parameter, i.e. {{{1|}}}, and displays a "mapped" string as a result), and uses that template to map every potential value, so that the values' "aliases" appear on the screen, and not the values themselves.
- mapping property=property name - Used for fields that select pages with 'combobox', 'tokens', 'listbox', and 'dropdown' input types. For each possible value, displays a SMW property from that page rather than the title of the page, but saves the title of the selected page(s) as the field value. Used in conjunction with the “values...” parameters to get the list of possible values.
- mapping cargo table=table name/mapping cargo field=field name - Similar to mapping property=, except it is used for Cargo fields.
Autocompletion
Two of the input types – tokens and combobox – use autocompletion: as the user starts typing, the input shows a dropdown list of possible completions.
If a field represents a Semantic MediaWiki property, or Cargo field, of type "Page", autocompletion will be enabled by default — the field will autocomplete on the names of all pages that are already pointed to by that property or field. For any other type, there is no default autocompletion, but you can achieve this same effect simply by setting the input type to either "combobox" or "tokens".
You can manually set a field to autocomplete on one of various sets of values, by using one of the "values ..." parameters – see the previous subsection, "Setting values and mappings".
You can also autocomplete based on values outside the wiki, contained in web pages, databases, files, etc.; see "Autocompleting on outside values", below for the various ways to do this. If a field is specified to hold multiple values, autocompletion will, by default, support multiple values: after a value is entered, and a delimiter placed, a new autocompletion will start for the next value. You can manually specify that a field should have multiple-value autocompletion, by adding the "list" parameter to the field's definition. You can also specify the delimiter for this list of values, using the "delimiter=..." parameter (the default is a comma).
By default, the maximum number of autocompletion possibilities that a field will offer is 1,000; this is for performance reasons. To change this number, change the value of $wgPageFormsMaxAutocompleteValues in LocalSettings.php.
Matching on every character
By default, Page Forms autocompletion matches on the beginning of every word in the set of possible values. However, you can change autocompletion to instead match on every character, by adding the following line to LocalSettings.php:
$wgPageFormsAutocompleteOnAllChars = true;
This feature is especially important for wikis that have values with non-ASCII characters, such as wikis in languages with non-Roman alphabets; since the default, word-based autocompletion doesn't yet work with non-ASCII characters.
Autocompleting on outside values
Autocompleting on values from outside the wiki is currently a rather intensive process, because you have to massage the outside data to get it into exactly the right format. Ideally this will change in the future, so that arbitrary lists of values can be used within forms. Until then, to have a field autocomplete on outside values, you have to take the following steps:
- Create a page/web service that takes in a substring via the query string, and displays a set of autocompletion values; the values should be in JSON format, and look like the JSON returned by the MediaWiki API (see here). This also makes it easy to autocomplete on the values from another wiki.
- Decide on a short string to represent this URL.
- Add a line to LocalSettings.php that looks like this:
$wgPageFormsAutocompletionURLs['URL-identifier-string'] = 'URL';
The URL in this line should look like a call to that web service, but with the substring replaced by the string "<substr>".
- Add the parameter "values from url=URL-identifier-string" to the relevant field in the form definition.
Uploading files
If a field in the form is meant to hold the name of an uploaded file (say, an image), you can allow users to upload this file directly through the form. This is done simply by adding the parameter “uploadable” to that field's declaration in the form definition. This will add a link reading “Upload file” next to this field in the form; if the user clicks on this link, it will pop up a “lightbox”-style window that lets the user upload a file. Once the user has done so, the window will close, and the field will contain the name of the uploaded file. (For more on uploading files, see here.)
If the field is configured to contain a list of values, the new file name will be appended to whatever was there before; otherwise, the file name will overwrite whatever the field contained before.
Parameters that can only be applied to fields that hold a list of uploaded files are:
- uploadable - Specifies that this is an uploadable field.
- image preview - Specifies that a thumbnail of the uploaded image should be placed under the field in the form.
- default filename=filename - Specifies the default filename for files uploaded with this field.
“show on select”
For inputs of type 'checkbox', 'checkboxes', 'radiobutton', 'dropdown' and 'listbox', the parameter show on select= can be used to specify that one or more elements on the page should only be displayed to the user if a certain value (or values) is selected within that input. The syntax for this parameter is:
- show on select=value 1=>element ID 1;value 2=>element ID 2;etc.
For inputs of type 'checkbox', simply “show on select=element ID” should be used.
Multiple values for the same field
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 here. 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).
Multiple-instance templates
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 on here is a good example of a form with multiple-instance templates. There's a button labeled "Add another"; clicking on it will create a new instance of that template and its fields. Instances can be removed, by clicking on the “Remove” button, and they can also be rearranged, by clicking on the “ribbed arrow” 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}}}
Embedded templates
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.
Defining the bottom of the form
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 (all except for “save and continue” and “run”) 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 wikitext, that they appear in in the form definition.
Enabling multiple field values
There are two parser functions defined by Page Forms, #arraymap and #arraymaptemplate, that enable holding multiple values within the same field, by applying the same semantic property to each element of a comma- (or otherwise-) delimited list (a comma-delimited list is a piece of text in which distinct values are separated by commas). There is nothing form-specific, or even semantic-specific, about these functions; but they seem to have not been necessary until Page Forms was created, which is why they're stored there. Of these, #arraymap is the more important: it's used much more frequently, and it's the one applied automatically within templates by both Special:CreateClass and Special:CreateTemplate when a field is specified to hold a list of values. #arraymaptemplate is useful when the mapping required is too complex for #arraymap.
#arraymap
The generic call for this function is:
{{#arraymap:value |delimiter |var |formula |new delimiter}}
The function splits the 'value' by the 'delimiter', and then, for each one, applies the same mapping that 'formula' does to 'var', and finally joins all the values again using the 'new delimiter'. For example, if you have a form that populates the field 'author', and you want that field to be able to hold multiple values, separated by commas; and you want each value to also be bolded, you could add the following to the template code:
{{#arraymap:{{{author|}}}|,|x|'''x'''}}
Essentially this function “maps” the formatting onto each comma-delimited value in the field. (The 'delimiter' parameter defaults to "," and 'new delimiter' defaults to ", " (note the extra space) if they are not set.) The user can thus enter all the values on the same line, with or without spaces around the commas. (Note, by the way, that the "x" is used here as an internal variable: if the property name itself contains the letter "x", that will lead to problems, and you should replace the letter "x" with some character or string that does not appear in the property name, like "@@@@".)
The 'new delimiter' parameter sets the text that's placed between values in the resulting output. It is optional, and is usually not set, because its default value – a comma plus a space – is generally what's needed. However, this parameter is useful in certain cases. It's especially helpful if none of the resulting values are actually displayed, because in that case you wouldn't want the output to be a string of commas. A common example of that is if the original value holds a list of category names, and each name gets turned into a category tag, but is not actually displayed. To avoid displaying commas in that case, you should set the 'new delimiter' value equal to a space, using something like " ", the HTML encoding for a space. (Using just "| " at the end won't work, because the MediaWiki parser will ignore it.) Here is how such a thing would be called:
{{#arraymap:{{{categories|}}}|,|x|[[Category:x]]| }}
If you use the 'CreateTemplate' or 'CreateClass' pages to create a template, and you specify that a field that can take more than one value, then an #arraymap call will be automatically added to the generated template.
#arraymaptemplate
There are some kinds of mapping that are complex enough that they cannot be placed in the #arraymap function. For this purpose, you can instead use the similar #arraymaptemplate function. To use this function, create a template that takes in a single field and applies the mapping you would like to that field. Then apply #arraymaptemplate onto the main template field just as you would with #arraymap, using the following format:
{{#arraymaptemplate:value |template |delimiter |new delimiter}}
...where 'template' is the name of the mapping template in question.
\n delimiter
For both #arraymap and #arraymaptemplate, the string “\n” in the value of either delimiter or new delimiter will get converted into a newline. If you want an actual line break to appear between values, you should have two newlines (i.e, "\n\n") as the delimiter, since MediaWiki requires two newlines in order to display a line break.
The “edit with form” tab
If a user is not allowed to edit a page that is form-editable, the tab will show up for them as "view form" instead; clicking on the tab will show the disabled form.
Getting "edit with form" to appear
There are three ways to get the 'edit with form' tab to appear for specific pages:
Based on category
The first, and recommended, way, is to use categories. To enable a page to have a tab in this way, you must do the following two steps:
- First define that page as belonging to a specific category. The best way to match pages with a category is to place a 'Category' tag inside the main template that defines this page type; that way, every page that uses this template will become part of this category.
- Once you have done that, place a function call like {{#default_form:form_name}} in the page for that category. (You can do this automatically if you create the category using the 'CreateCategory' page.)
Based on namespace
The second possible way is to match the pages' namespace to a form. You can do that by placing a #default_form function in the page defining that namespace. If, for instance, your wiki is called 'MyWiki', and the namespace you want to associate with a form is 'User', the page in which you need to add the #default_form cal will probably be called 'MyWiki:User' (you will probably need to create this page). If the namespace you want a default form for is the main one (i.e., the one with no name), you will need to create and add #default_form to the page called 'MyWiki:Main', or whatever the main namespace is called in the language of this wiki.
Once you've added this function, every page within that namespace will have that form associated with it, unless it already belongs to a category that has an associated form (categories take precedence over namespaces).
Within the page
You can also add a call to #default_form to any regular page, to set the form just for that page. This is especially useful when the category and namespace options aren't possible, such as when pages belong to multiple categories that have different default forms.
Configuring the editing tabs
For pages that have an “edit with form” tab, you may want the regular “edit” tab to be renamed or even removed altogether. There are flags you can set in "LocalSettings.php" to change the appearance of the editing tabs:
- $wgPageFormsRenameEditTabs - if set to true, renames the “edit with form” tab to “edit”, and the “edit” tab to “edit source” (in whatever language the wiki is being viewed in)
- $wgPageFormsRenameMainEditTab - if set to true, renames only the “edit” tab to “edit source” (in whatever language the wiki is being viewed in)
- $wgGroupPermissions[...]['viewedittab'] - can be set, for different types of viewers, to toggle whether each type will see the regular edit tab. One common modification is to set it to false normally (i.e. for viewer type '*'), and to true for 'sysop' viewers:
- $wgGroupPermissions['*']['viewedittab'] = false;
- $wgGroupPermissions['sysop']['viewedittab'] = true;
If these settings are added to LocalSettings.php, they should be placed in the file after the inclusion of Page Forms.
Linking to forms
How do you get users to forms to create the pages in the first place? The standard way is via the #forminput parser function call, which displays a single input for users to enter the name of a page; if they enter such a name and click the button, they are sent to a form to create that page – unless a page with that name already exists, in which case they are sent to a form for editing the existing page. This is what is known as the "two-step process". The reason for the initial step, of having the user first enter the page name, is to ensure that users don't accidentally overwrite existing pages. This process is so standard that it is built into the default forms produced by Page Forms' Special:CreateForm and Special:CreateClass helper pages: any form-definition page created by Page Forms includes, at the top, a call to #forminput, so that users who go to that form page can automatically start to use the form.
However, it's also possible to skip the first step, of entering the page name – that's what you should do if the form contains a formula for setting the page name based on the user input. That's the "one-step process", and it uses the parser function #formlink instead of #forminput.
Query forms, which use Special:RunQuery, have their own linking method, using the parser function #queryformlink – we'll get to those on here.
The two-step process
The two-step process, i.e. the standard way to get users to forms, is done using the #forminput parser function.
Using #forminput
Here is the syntax of the #forminput parser function:
{{#forminput:form= |size= |default value= |button text= |query string= |query string parameters |autocomplete on category= |autocomplete on namespace= |remote autocompletion |placeholder= |popup}}
All arguments are optional. An explanation of the parameters:
- form= - the name of the PF form to be used. If a comma-separated list of forms is passed in, a dropdown will appear, letting the user choose among those forms. If this parameter is left empty, a dropdown will appear letting the user choose among all existing forms.
- size= - the size of the text input (default is 25).
- default value= - the starting value of the input (default is blank).
- button text= - the text that will appear on the "submit" button (default is "Create or edit page").
- query string= - you can use this option to pass information to the form; this information generally takes the form of templateName[fieldName]=value. It should look like a typical URL query string; an example would be “query string=namespace=User&User[Is_employee]=yes”. Additionally, any query string values can be passed directly in as parameters – so the values above could instead be passed in as “|namespace=User|User[Is_employee]=yes”.
- autocomplete on category= - adds autocompletion to the input, using the names of all pages in a specific category.
- autocomplete on namespace= - adds autocompletion to the input, using the names of all pages in a specific namespace (only one of these two can be used).
- remote autocompletion - specifies that autocompletion values should be retrieved dynamically from the server, instead of directly from a list of values hidden in the page's HTML (thus allowing many more values).
- placeholder= - "placeholder" text that appears in the form input before the user types anything.
- namespace selector= - specifies that a dropdown should be placed before the input for the page name, letting the user choose from a set of possible namespaces for this page; the value for this parameter holds that set of namespace names, separated by commas. (For the main namespace, just have a blank value, like ",User,Project".)
- popup - opens the form in a popup window.
- reload - if "popup" or “returnto” are specified, causes the page the user returns to to get reloaded once the form has been submitted.
- no autofocus - by default; the form input gets autofocus, i.e., the cursor is placed in the input when the page loads; this parameter specifies not to do this.
- returnto= - the name of a page that the user will be sent to after submitting the form, instead of simply going to the saved page.
Adding pages of a specific namespace
You can have a page-input form create pages within a specific namespace (like 'User:') by default, without forcing users to type in that namespace every time. To do that, add “namespace=namespace-name” to the query string= parameter.
Adding subpages
In MediaWiki, you can create subpages by including a slash in the page name (see here). To have the page that's added automatically be a subpage, you can add a value for “super_page=” in the query string. To make it a subpage of the current page, you can set this value to “super_page={{FULLPAGENAME}}”. This will prepend a “current-page-name/” onto the beginning of the page name that the user types in.
The one-step process
You can have the name of the page created by the form be set automatically, by adding a "page name" parameter within the form definition's "info" tag. There are two types of "variables" one can include in the value for this parameter:
- <TemplateName[FieldName]> – gets replaced with the value for the specified field FieldName in the specified template TemplateName.
- <unique number> – by default, gets replaced by the lowest number for which the page title that's generated is unique. Normally, this value starts out as blank, then goes to 2, then 3, etc. However, one can manually set the starting number for this value, by adding a “start=” parameter; this number must be 0 or higher. For instance, to have the number start at 1 and go upward, you should set the tag to be <unique number;start=1>. You can also instead set it to be a random six-digit number, by adding the "random" parameter, so that the tag looks like "<unique number;random>". Note that the parameter in either case is delimited by a semicolon.
Note that the "page name=" value cannot start with "<unique number>", due to a bug in Page Forms; there has to be some text before that. And it cannot contain the character "#", because MediaWiki does not allow pound signs in page titles.
As an example, imagine a form for storing notable quotes. Its {{{info}}} tag could have a parameter of "page name=<Quote[Author name]> quote <unique number;start=1>". This would include the author's name in the name of every quote page, as well as a number to guarantee the uniqueness of every opinion-item page added. A user could then go to the URL "http://mywiki.com/wiki/Special:FormEdit/Quote" and fill out the form; if they set the author to be "Ernest Hemingway", and no other quotes in the wiki had him as an author, then hitting the "Save page" button would result in a new page called "Ernest Hemingway quote 1" .
The "start" value can have leading zeroes; a value of "001", for instance, would lead to pages that had the value "001", then "002", etc.
The "page name=" value gets parsed by the MediaWiki parser, so you can also add parser functions, pre-defined variables, etc. into the value.
Note that users must be sent to the page "Special:FormEdit/form-name" for this automatic page-setting to work; if they somehow end up at a #forminput call and are prompted for a page name, that name will override whatever the automatic page name would be.
Using #formlink
If you want, you can generate a link to a “one-step process” form using the "#formlink" parser function, instead of creating the URL directly. This function is called as:
{{#formlink:form= |link text= |link type= |query string= |query string parameters |target= |tooltip= |popup |reload |new window |returnto=}}
The "form=", query string, "popup", “reload” and “returnto=” arguments work much the same way that their equivalents in #forminput work, and "link text=" works like #forminput's "button text=". The "link type=" argument sets the display of the link: if it's set to "button", the link will show up as a button; if it's set to "post button", it will be a button that sends the query-string value(s) using "POST" instead of via the URL – this is helpful when a lot of data has to be preloaded, and it is more robust with special characters like line breaks in the query string; if it's set to blank or anything else, it will show up as a regular link. The "target=" parameter shouldn't usually be used, but it sets the target page to be edited, if you want to link to the editing of a specific page. The "tooltip=" parameter displays a "tooltip", displayed if a user hovers the link. The “new window” parameter opens the form in a new window or tab, depending on the browser.
An example call to #formlink would be:
{{#formlink:form=Quote|link text=Add a quote for this author|link type=button|query string=Quote[Author]={{PAGENAME}}}}
This will link from the page, via a button, to a form for adding a quote, with the "Author" field filled in with the current page name. If there are multiple values, they should be separated by "&".
Pointing red links to a form
In MediaWiki, links to nonexistent pages are called “red links”, because they are usually colored red. By default, these links go to a page for adding the article to the wiki using the standard edit interface. However, if that nonexistent page is being pointed to by a semantic property, the red link can instead take the user to the correct PF form to add the page.
To have a specific link (either on its own, or within a template) point to a form if the page it is pointing to does not exist, use the #formredlink parser function. A typical call to #formredlink will go inside a template, and will look like:
{{#formredlink:target={{{PageNameParameter|}}}|form=FormName}}
The overall syntax of #formredlink is:
{{#formredlink:form=|link text=|existing page link text=|link type=|query string=|target=|tooltip=|popup|new window|create page}}
These parameters are very similar to those of #formlink (see above). It has two additional parameters:
- existing page link text= - sets the text of the link when the target page being pointed to exists already (the "link text=" parameter takes effect only when the target does not exist).
- create page - causes red-linked pages to get automatically created by the system.
There may be times when you are not sure which form a linked-to page will use; it could be one of a number of choices. You can set it so that the user gets other possibilities when they click on the red link, by adding one or more "alt_form" parameters to the #formredlink call, each with its own number.
Preloading data
You may want a form to already contain some data when the user goes to it. (Note that this only applies to adding new data, or to query forms; for editing an existing page, there is no way to set the contents of the form to anything other than the current contents of that page.) There are various ways to do this:
- Specify a "default" value for whatever fields you want to have a value for in the form.
- Specify a "preload" page for the "free text" input, which will preload the free text field with the contents of that page.
- Add 'preload=preload-page-name' to the query string value in the #forminput call; this will preload the entire form with the contents of that page.
- Similarly, you can add a "preload=..." value to the query string for a 'FormStart' or 'FormEdit' URL.
- Add "template-name[field-name]=field-value" to the query string value in the 'forminput' call, to set the value for a specific field. To preload values for more than one field, use "&": "template1[field1]=val1&template1[field2]=val2".
- Similarly, you can add a value for a specific field to the URL query string for 'FormStart' or 'FormEdit'.
- Finally, you can create your own custom handling, using the “PageForms::EditFormPreloadText” hook. If another extension calls this hook, it can preload data however it wants. The function registered with this hook should have a header like:
function-name(&$page_contents, $page_title, $form_title)
Creating query forms
Forms can also be used for querying, as opposed to adding or editing data. In other words, you can create a form that will not modify any pages, but will instead be used for searching existing data – in which a user enters values in different fields and then sees some set of pages that match those fields.
To have query forms, you need to use the Special:RunQuery page, which displays a form in a manner similar to Special:FormEdit, but with no associated target page. Instead, when the user submits the form by hitting the "Run query" button, the user stays on the Special:RunQuery page, but now the page shows what the template looks like when displayed with the values they entered. The template that the form uses should most likely contain one or more Semantic MediaWiki inline queries, to query data using values the user entered.
The "Run query" button
By default, a button called "Run query" shows up at the bottom of forms if they are accessed via Special:RunQuery. You can change the location and text of this button, using the tag "{{{standard input|run query}}}" within the form definition. (This tag can also accept other parameters, like “label=” and “class=”.)
Creating links to query forms
Once a query form has been created, you can link to it using syntax that looks like this:
[[Special:RunQuery/query form name]]
However, the preferred solution, because it's easier and more powerful, is to use the #queryformlink parser function. A basic call to that function would look like:
{{#queryformlink:form=query form name}}
Here's the complete syntax of #queryformlink:
{{#queryformlink:form= |link text= |link type= |query string= |query string parameters |tooltip= |popup}}
These parameters are almost identical to the ones used by #formlink (here).
Embedding query forms
You can also embed a query form within another page. To do that, add the following in a page where you want the query form to appear:
{{Special:RunQuery/query form name}}
Modifying pages automatically
You can create links that, when clicked on, create or edit pages automatically in the background, with a preloaded set of values, using the #autoedit parser function. This function is called, and is displayed, in a very similar manner to #formlink – the difference is that the link only performs an action in the background, instead of bringing the user to a form. The syntax for #autoedit is
{{#autoedit:form= |target= |link text= |link type= |query string= |query string parameters |reload }}
All these parameters but 'reload' work in the same way as they do in #formlink; 'reload', if added to the call, reloads the current page after the link is clicked.
As an example, let's say you want to create a simple voting scheme, letting users vote between "Vanilla", "Chocolate" and "Strawberry". You have a page for each, and each one contains a template called "Flavor", with a field called "Num votes" – that field, in turn, sets a semantic property called "Has number of votes". And there is a form, also called "Flavor", to edit such pages. To create a link that, when clicked, increments the number of votes in the "Vanilla" page by one, you could place the following call on the page:
{{#autoedit:form=Flavor|target=Vanilla|link text=Vote for Vanilla|query string=Flavor[Num votes]={{#expr:{{#show:Vanilla|?Has number of votes}} + 1}} }}
What happens when a user clicks on such a link? They'll stay on that page, but the link will turn into text that reads “Successfully modified target page using form form name.” If the user refreshes the page, or goes to that page later, they'll see the original link again – and they can click on it; there's no limit to the number of times a user can click on an #autoedit link. (Though you can embed an #autoedit call within an #if call, if you have ParserFunctions installed, to only display it for certain users, or in certain situations.)
This functionality is also available via the MediaWiki API (here), as the "pfautoedit" action – this enables outside scripts, and bots, to modify template calls within wiki pages. You can find the full documentation on this by searching for "pfautoedit" on your wiki's api.php file; essentially the parameters are the same as for #autoedit.