Section: Displaying a form in a template
« Initializing a form | ^ jForms: automatic forms | Using a form after a submit » |
− Table of content
To display a form and its data, you could call getAllData
on your form
object and assign its returned array to a template. With it, you'll be able to
generate your HTML form along with its data. if you want to display input
errors, call getErrors
to retrieve them and again display them as you like
in your template.
However there are some template plugins in Jelix, to prevent you from doing this long and sometimes boring task. They even do a lot more:
- display each control field as described in your XML form,
- display each control label in
<label>
tag to improve ergonomy and accessibility, - display error messages,
- display help messages,
- generate javascript for client-side checking before posting data,
- valid HTML generated and good support of accessibility,
- ids and classes on elements to ease styling.
Full automatic form display with formfull ¶
For you in a hurry, this template plugin will fully display your form. Its name:
formfull
. With it, you won't control how the form is displayed,
the order of fields, how their labels are displayed. However you can customize
display of help and error messages, and indicate some options for the widgets.
Widgets are the objects that generate the HTML and javascript of each fields.
Here are the arguments of formfull
, in the order:
- your form object
- a selector specifying the target action
- optional:
- an array containing extra url parameters (other than fields data)
- the name of the builder ('html' is the only provided builder)
- an array containing options for the builder
Example in your controller:
$form = jForms::get('myform');
$tpl = new jTpl();
$tpl->assign('form', $form);
And in your template :
<h1>My form</h1>
<p>Fill this form :</p>
{formfull $form, 'mymodule~default:save'}
Labels and control fields will be displayed in a table, and submit buttons in a div below.
Note: because of some limitations of the plugin formfull and the template engine, don't use the plugin inside a loop, where the variable passed to the plugin is generated by the loop (typically, in a foreach). In this case, JS and CSS files won't be loaded in the page. A solution is to indicate yourself all CSS and JS files needed by your form with the meta_html plugin.
Customizing display ¶
There are other plugins than formfull
, to control how your form is
displayed and precisely in which markup your form controls are wrapped.
The first one form
is the equivalent to formfull
except that its a block
plugin. It means that it has an end tag and should contains other plugins and
markup controlling the display of your form. Arguments for form
are :
- your form object
- a selector specifying the target action
- optional:
- an array containing extra url parameters (other than fields data)
- the name of the builder ('html' by default)
- an array containing options for the builder
{form $myform, 'mymodule~default:save',
array('parameter1' => 'foo', 'parameter2' => 'bar'},
'html',
array(
'attributes' =>
array('class' => 'css_class_on_form_element',
'otherHtmlAttribute' => 'value'),
'errorDecorator' => 'myErrorDecorator',
'plugins' => array(
'myTextField' => 'pluginForTextField',
'myDateField' => 'pluginForDateField')
)}
Note: As for the formfull plugin, there are some limitations in the plugin form and the template engine, so don't use the plugin inside a loop, where the variable passed to the plugin is generated by the loop (typically, in a foreach). In this case, JS and CSS files won't be loaded in the page. A solution is to indicate yourself all CSS and JS files needed by your form with the meta_html plugin.
Simple display ¶
formcontrols
plugins loops on form controls (neither submits nor reset). It
is a block plugin. Within it, ctrl_label
and ctrl_control
plugins will
display respectively label and field of current control. To display submit
buttons or reset, use formsubmit
and formreset
.
Example:
{form $form, 'mymodule~default:save'}
<fieldset><legend>Fill : </legend>
{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formreset}{formsubmit} </div>
{/form}
Note that form fields will be displayed in the order of their declaration in your XML file. Note also that template here is totally independent of form content and could be reused with more forms.
Advanced display ¶
Some controls need to be displayed differently. To achieve this, you can use
ifctrl
inside formcontrols
. Its argument is a list of control names. The
code below adds a class on 'name' and 'firstname' controls only:
{form $form, 'mymodule~default:save'}
<fieldset><legend>Your identtity : </legend>
{formcontrols}
<p {ifctrl 'nom', 'prenom'}class="help-needed"{/ifctrl}
{ifctrl 'adresse'}class="address"{/ifctrl}>
{ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
You have also ifctrltype
which allow to test the type of the control (which is the name of the xml element).
It should be used inside a formcontrols
bloc.
{ifctrltype 'upload', 'upload2', 'image'}<p>Please, do not upload no heavy files.</p>{/ifctrltype}
You can indicate a list of control names to formcontrols
plugin. It will loop
only on those controls.
{form $form, 'mymodule~default:save'}
<fieldset><legend>Identity : </legend>
{formcontrols array('lastname','firstname','address')}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<fieldset><legend>Other fields : </legend>
{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formsubmit} </div>
{/form}
Above, we display a series of controls in a first fieldset (lastname, firstname
and address) and the others in a second fieldset: formcontrols
loops over
controls not already displayed.
Note that ctrl_label
and ctrl_control
also function outside of
formcontrols
. In that case, you should indicate a control name.
{form $form, 'mymodule~default:save'}
<fieldset><legend>Identity : </legend>
<table>
<tr><td>{ctrl_label 'lastname'}</td><td>{ctrl_control 'lastname'}</td> </tr>
<tr><td>{ctrl_label 'firstname'}</td><td>{ctrl_control 'firstname'}</td></tr>
</table>
</fieldset>
<fieldset><legend>Other fields : </legend>
{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formsubmit} </div>
{/form}
Lastname and firstname fields are displayed precisely in a table whereas other
fields are displayed with formcontrols
.
An other tag ifctrlexists
allows to check if a control exists. This is useful when some
controls are deactivated:
<table>
{ifctrlexists 'lastname'}
<tr><td>{ctrl_label 'lastname'}</td><td>{ctrl_control 'lastname'}</td> </tr>
{/ifctrlexists}
<tr><td>{ctrl_label 'firstname'}</td><td>{ctrl_control 'firstname'}</td></tr>
</table>
To know more about how to customize the display of controls in HTML, see the dedicated page.
Customizing display of password controls ¶
Beware that if a password control defines a confirm field (<confirm>
tag
in XML) you should control either the display of password
field and
confirm
field. The confirm control name is a concatenation of password
control name and a suffix _confirm
.
See example below:
{form $form, 'mymodule~default:save'}
<fieldset><legend>Account creation : </legend>
<table>
<tr><td>{ctrl_label 'login'}</td><td>{ctrl_control 'login'}</td> </tr>
<tr><td>{ctrl_label 'password'}</td><td>{ctrl_control 'password'}</td></tr>
</table>
</fieldset>
<fieldset><legend>Other infos : </legend>
{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formsubmit} </div>
{/form}
Confirm field will appear in the second fieldset and not near password field in the example above. To do so, just display 'password_confirm' in a row below 'password' :
<table>
<tr><td>{ctrl_label 'login'}</td><td>{ctrl_control 'login'}</td> </tr>
<tr><td>{ctrl_label 'password'}</td><td>{ctrl_control 'password'}</td></tr>
<tr><td>{ctrl_label 'password_confirm'}</td><td>{ctrl_control 'password_confirm'}</td></tr>
</table>
On the contrary, you should not take care of confirm field in formcontrols
loop.
Customizing display of submit buttons ¶
As you may recall, formsubmit
template plugin displays a submit button
declared in your form. But if one declares more than one submit button,
formsubmit
will display only the first one. In that case, use
formsubmits
(note the ending s). This block template loops over submit
buttons:
<ul>
{formsubmits}
<li>{formsubmit}</li>
{/formsubmits}
</ul>
Another way is to use formsubmit
multiple times indicating each submit name :
<div> {formsubmit 'preview'} {formsubmit 'save'} </div>
- *Beware :
{formsubmits}
loops over submit controls**, not submit - *items**! It is not possible to loop over submit items (see ticket #429).
Choosing a generator ¶
To generate HTML code, template plugins call a generator (or builder) which is a component of jForms.
It is possible to use another generator than the default one ('html'). You would want to generate a form based on a library like ExtJS, or a form built using XForms etc.
Generators are themselves plugins. Furthermore, the generator 'html' is also extensible: you can provide your own plugins to generate HTML code of some specific controls, without redefining the whole generator. These are "formwidget" plugins.
Each generator has a name. The default generator is, as we already say, 'html'. It is specified in the parameter defaultJformsBuilder of the main configuration.
Note: since Jelix 1.5, architecture of generators has been modified. But it is still possible to use olders generators. To use them, you should prefix their name with "legacy.". For example, to use the deprecated builder 'htmllight', indicate 'legacy.htmllight'. Read manual of previous version of Jelix to know how to use them. Note that these generators are deprecated and will be removed from Jelix 1.8.
To specify your own generator for th whole application, modify this parameter in the configuration:
[tplplugins]
defaultJformsBuilder = myformbuilder
To achieve a fine-grained control, you can even choose a generator in {form}
ou {formfull}
(as fourth argument) :
{formfull $form, 'mymodule~default:save', array(), 'legacy.htmllight'}
Those plugins support a fifth parameter which is an array of options passed to the generator. These options depends on the used generator. (errorDecorator and method for 'html'). One of them is "plugins" (aka widgets), which allow to indicate which plugin to use for some controls.
To know more about the 'html' generator and its options, see the dedicated page: "html" generator.
Tip: You can of course create a new generator as inheriting from an existing one. That way, you can customize only some of the output or set an option directly in its constructor. ...