DataForms

Basic setup - A form that saves to the same page the form is displayed on.

Step One - add cookbook recipe, install recipe, define the first $PmForm

To get a basic form that can be used to save data, install the Cookbook:PmForm recipe into your cookbook folder, and then add the following lines to a local customization file (e.g., local/config.php):

include_once('cookbook/pmform.php');
$PmForm['savedata'] = 'saveto={$FullName} form=#dataform fmt=#datapost';
Note: This entry into the $PmForm array is required before a form will function. savedata is the index for this particular form. saveto must point to the page the data will be saved on (in this case, it uses the value {$FullName}so that it changes to the name of the currently viewed page). form is the template to use to produce the form. fmt is the template to use to format the output of the data.

Note that the saveto= parameter is not allowed to come directly from the data submitted from the form.

Step Two - create form template (form=#dataform)

Custom forms should be created on LocalTemplates (other options below). Do not alter PmFormTemplates.

Here is a simple PmForm for our example:

[[#dataform]]
(:input pmform target=savedata :)
(:input default source={*$FullName} :)
(:input default request=1 :)
(:messages:)
|| Name:||(:input text $:name size=25 :) ||
|| Email:||(:input text $:email size=25 :) ||
(:input submit :)
(:input end:)
[[#dataformend]]

Use anchor tags to define the start and end of the template, and make sure to use the same template name you used in the config.php $PmForm definition for "form=" - in this example it's "dataform". The first line in the form tells PmWiki that you are using the PmForm recipe (:input pmform:). You also need to tell PmWiki which index for the $PmForm array in config.php it should be looking at, so you can add the target index for our form here: (:input pmform target=savedata :)

(:input default source={*$FullName} :) instructs the form to auto-fill with the data values from the current page if they are available. This is a nice time-saving feature if you don't want to re-type all fields of a form to make a correction.

(:input default request=1 :)

(:messages:) tells PmWiki where to put feedback messages for the form so that the user knows when the form fails, or succeeds and why.

Next is the body of the form where we request data from the user. This form only requests 2 pieces of information: name and email address, both of which work identically. The line || Name:||(:input text $:name size=25 :) || sets up a small table for the form on the page. In the left column is the field label "Name:" and on the right is the actual text input box. $:name is the important part here. This shortcut indicates the page text variable that will be saved -- or retrieved if the (:input default source=...:) is defined -- for that line of the form.

In most ways, the form follows the usual PmWiki form creation rules, with the special directives already noted.

Step Three - create form processing template (fmt=#datapost)

[[#datapost]]
(:template defaults savevars=$:name,$:email :)
[[#datapostend]]

Again, you need to use anchor tags to define the start and end of the data processing (post) template, and the name used must match the name used in the config.php $PmForm definition. The (:template defaults savevars=$:name,$:email :) sets the default for this form to be to save the data (savevars) and tells it which variables to save (name & email) from the form submission.

NOTE: Do not put spaces between comma separated list field names. This will not work (space between name and email):

(:template defaults savevars=$:name, $:email :)

Step Four - place the form in a wiki page

Wherever you want this new data form to appear, use the directive with the index of the corresponding form format in the $PmForm array. Create a new page on the website, or try this in the WikiSandbox.

(:pmform savedata:)

In this line, use the index created in the config.php $PmForm command (in our example it's "savedata").

To make it more interesting you may want to actually use the data. The data will be saved so that it's invisible to viewers unless you use the data, as in this example:

{$:name} can be reached at {$:email}.

Alternative template pages

To retrieve a form for use, the template must be specified in the $PmForm array. If you wish to use a custom template, use fmt=MyCustomTemplate if there's only one form on the page, or fmt=MyCustomTemplate#post to define the anchor that wraps the template.


Can I make the form to save data to page formed from page text variables like: {$:artist}{$:album}{$:track} or page made from timestamps like {(ftime fmt="%Y%m%d%H%M%S")} ?

Vekkuli

Any possibility there could be a sandbox to play with this a bit? Maybe it's already there, but I'm not finding it... Peter Bowers February 12, 2009, at 01:29 AM


There's a major bug with radio buttons and checkboxes where the displayed value is inverted, e.g. if the value is (:somevar::) then it will show as ON (ticked); if (:somevar:on:) then it will show as OFF (unticked). Try this

In your config:

$PmForm['Worksheet'] = 'saveto={$FullName} form=#dataform_Worksheet fmt=#datapost_Worksheet';

In your Site.LocalTemplates:

[[#dataform_Worksheet]]
(:input pmform target=Worksheet :)
(:input default source={*$FullName} :)
(:input default request=1 :)
(:messages:)
* (:input checkbox $:var_ws_idea :) Compelling Idea
* (:input checkbox $:var_ws_premise :) Premise
* (:input text $:var_ws_thetext :) The Text
* (:input radio $:var_ws_radio1 :) radio 1
* (:input radio $:var_ws_radio2 :) radio 2

(:input submit value="Save Changes" :)
(:input end:)
[[#dataform_Worksheetend]]

[[#datapost_Worksheet]]
(:template defaults savevars=$:var_ws_idea,$:var_ws_premise,$:var_ws_thetext,$:var_ws_radio1,$:var_ws_radio2 :)
[[#datapost_Worksheetend]]

And in your page where you want the form:

(:pmform Worksheet:)

On the page, set the checkboxes in various combos and you'll see they get inverted after clicking the 'save changes' button.

Andrew Ferguson, 18 June 2010 (fergicide at gmail dot com)

How to create a cancel button

Put this in your configuration file, before you include pmform.php:
  if(@$_REQUEST['action']=='pmform' && @$_REQUEST['cancel']>'')
  {
    Redirect($pagename);
    exit;
  }

Then, in your template, use this markup:
(:input submit name=cancel value="Cancel":)


Output Issues

Line breaks

PmForm's post output will insert newline characters in ways that are not consistent with PageList Templates and may affect list output or add spaces to the actual page markup if the data is invisible. Thus to form a bullet list, eliminate extra linebreaks like this:

[[#goingpost]](:template defaults where=below :)(:template require author errmsg="$[Missing name]":)*"{$$anchor}" ~{$$author}
[[#goingpostend]]

There must be a linebreak before each anchor tag. If you remove the linebreak before [[#goingpostend]] the output will continue to the next anchor tag.


Suggestion

Use a HoneyPot on a comment form or any form that is publicly accessible to prevent spambots from filling in and submitting forms on your website. They do work to prevent comment spam and email spam.

 0: 00.00 00.00 config start
 1: 00.01 00.00 config end
 2: 00.06 MarkupToHTML begin
 3: 00.23 MarkupToHTML end
 4: 00.24 MarkupToHTML begin
 5: 00.26 ReadApprovedUrls SiteAdmin.ApprovedUrls begin
 6: 00.26 ReadApprovedUrls SiteAdmin.ApprovedUrls end
 7: 00.32 MarkupToHTML end
 8: 00.32 MarkupToHTML begin
 9: 00.33 MarkupToHTML end
10: 00.34 now