Form Generator
Please note that the form generator is a separate feature that should be additionally purchased. Contact your imperia sales person for further information.
Invocation#
In order to use the form generator you should place the following code in your template:
<?imperia form_generator
id: SOME_ID
?>
//The following code is wrapped for representation purposes
#IF(NOT <!--XX-editmode-->)
<form action="/cgi-bin/form-generator-action-wrapper.pl" method="POST">
<input type="hidden" name="__form_generator_path" value="<!--XX-directory-->/
<!--XX-filename-->" />
#ENDIF
<div class="i-form-generator-field-drop" style="width: 500px; height: 300px;
border: 1px solid grey; float: left;">
#IF(<!--XX-editmode-->)
<input name="IMPERIA:my_fields_options" type="hidden"
data-field-control="options"/>
<input name="IMPERIA:my_fields" type="hidden" data-field-control="html"/>
#ELSE
<!--XX-my_fields-->
#ENDIF
</div>
<br style="clear: both;"/>
#IF(NOT <!--XX-editmode-->)
</form>
#ENDIF
The processing instruction provides an EDIT-mode controller from which various form fields can be Drag and Drop into drop zones. Those drop zones can be any block HTML container that has a i-form-generator-field-drop
class name.
Important
In order for the form generator to work the forms should be enabled for the template processor (Menu > System > General Settings > Template processor > Allow forms).
Form Generator Options#
The EDIT-mode controller has several options that determine how the container is displayed in EDIT-mode:
<?imperia form_generator
id: SOME_ID
custom_fields:1
placeholder_polyfill:true
?>
At present, the following options are recognised:
id#
This is the HTML id
of the control container. It is optional and it should be unique.
popup#
The default value of this option is false
and the position of the EDIT-mode control container is determined by the position of the PI itself. If the value is set to true
, the control container is hidden by default. In order to call it the user has to click on the drop zone and the control container appears next to it.
placeholder_polyfill#
If this option is set to true, a polyfill is inserted into the page, providing support for the HTML5 placeholder attribute for browsers that don't support that attribute natively.
slide#
The default value of this option is false
and the position of the EDIT-mode control container is determined by the position of the PI itself. If the value is set to true
, the control container is set on the far right of the web page and only its left edge is visible. The user has to click on that visible part in order to show the whole controller.
custom_fields#
The default value of this option is false
.
Important
In order to display customized fields the value of this option must be true
.
Multiple Control Containers#
It is possible to have more than one control containers per page. However, since the drop zones are not bound to any particular controller, there is no need to have more than one.
Important
Using more than one sliding EDIT-mode controllers is not advisable since their position is fixed and they will be rendered on top of each other with only the topmost visible.
Drop Zone#
A drop zone is the place where the selected forms can be dropped. It can be any block element HTML container that has a i-form-generator-field-drop
class. Other than that the container can be styled freely.
In EDIT-mode the drop container has to contain two hidden input fields. Those fields can have any names, as long as they are unique.
Important
Both fields must have a specific data-field-control
attribute that defines how the generator uses them.
The data-field-control
has two possible values: options
and html
. A field with an options
value contains the current options and state of the dropped fields in the drop zone. A field with an html
value contains the actual HTML representation of the dropped fields. In order to show the dropped form fields in other modes you should use the <!--XX-my_fields--> command (where “my_fields” is the defined name of the hidden input).
The Form Element#
In order for the form generator to have any effect, the various drop zones have to be enclosed with one or more form elements. It is important to exclude these forms in EDIT-mode, otherwise the resulting nested form elements will produce undefined behavior.
Form Fields#
The fields available to form generators on a given page are defined as JavaScript templates. You can find the current set of defined fields in VIEW-DIR/layout/editmode/pi/form_generator/default_fields.html
. Additionally, you can define custom fields and either place them directly in the template or include them automatically from VIEW-DIR/layout/editmode/pi/form_generator/custom_fields.html
, if that file exists.
Creating Custom Fields#
To make a custom field begin by marking the beginning and end of each custom field with <--custom_field_start-->
and <--custom_field_end-->
.
The HTML code should be wrapped in a container element, that must have the attributes data-field-type
and data-field-label
as a minimum. The data-field-type
attribute must have a unique value. Those attributes define the type of field it is and the label for the field's select box.
This container element must have another container element within it with the class imperia-field
or imperia-field-macro
.
The attribute data-field-no-preview
is used to either hide or display the custom fields within the EDIT-mode controller.
Since the field container will be replaced by a special <script type="text/i-field-tmpl" class="custom-field-tmpl">
element you should not place verbatim script tags within the container. To place a script element you must escape the closing script tag using: </#{"script"}>
The following is an example of a custom field:
<!--custom_field_start-->
//WRAPPED FOR REPRESENTATION PURPOSES
<div data-field-type="custom_text" data-field-label="Custom text"
data-field-no-preview="true">
<div class="imperia-field imperia-field-text">
<ul class="imperia-field-errors"></ul>
<label for="#{id}">#{label || '{% __('Field label') %}'}</label>
<input type="text" value="#{value}" id="#{id}" placeholder="#{placeholder}"
#{#if (required)} required="true" #{#endif}
#{#if (name)} #{nameattr}="#{name}" #{#endif}/>
#{#if (helptext)}
<span class="imperia-field-help-text">#{helptext}</span>
#{#endif}
</div>
<script type="text/javascript">
/* Some javascript code */
</script>
</div>
<!--custom_field_end-->
#{label}
, #{name}
, #{value}
, #{helptext}
and #{placeholder}
will be substituted with user-supplied values. The #{name}
token appears only in SAVE mode.
You can also specify a #{required} token. A checkbox appears in the field's configuration dialog and its state will be reflected in the token.
The #{\#if (name)}
control token block checks whether a name is supplied, and only then prints out the name attribute. The #{nameattr}
token is always equal to “name”. It is replaced, so that it does not appear in a document's meta-info.
#{id}
tokens are randomly generated.
Creating a Multi-valued Field#
To create a multi-valued field, use a #{values} token. It will create an array of values, which can be looped using the #{#for item (values)} control token block. Each item has a “label” and “value”, that can be accessed using #{item.label} or #{item.value}.
Creating a Macro Field#
Creating a macro field is done in the same way as a normal field. The difference is that the container requires an additional attribute data-field-macro
with value set to true.
Within a macro field you can reference normal fields using #{field_TYPE}, where “TYPE” is the value of the type attribute of any defined regular field.
Note
Non-macro fields cannot contain references and a macro field cannot contain another macro field.
The following is an example of a macro field:
<!--custom_field_start-->
<div data-field-type="sender" data-field-label="Sender" data-field-macro="true">
<div class="imperia-field-macro imperia-field-macro-sender">
<div style="float: left;"> #{field_email} </div>
<div style="float: left;"> #{field_custom_text} </div>
<br style="clear: both"/>
#{field_hr}
</div>
</div>
<!--custom_field_end-->
Form Submission and Validation#
In general, the form itself is not under the control of the PI. A script located in /cgi-bin/form-generator-action-wrapper.pl
provides basic server-side form validation and actions. That script does two things:
Validation
When a form is submitted, fields under generator control are checked. If a field is marked as “required”, the validation fails if the value is empty. If a field is a type “email”, the validation fails if the value is not a syntactically correct e-mail address.
If the validation fails, the user is taken back to the form. An error message is displayed next to the invalid field if the page contains jQuery or the browser supports element.querySeletorAll.
On success, the user id redirected to the URI, specified under __form_generator_success_uri in the meta information of the document. In case that field is not provided, the user is taken back to the form page.
Form Actions
Form actions are defined as a list of plug-in names in the meta information of a document under __form_generator_actions. Currently, the generator provides one action plug in. See E-mail Action Configuration.
It is required that the input field __form_generator_path is submitted with the form itself. That filed must contain the path to the document, so its value will most likely be <!--XX-directory-->/<!--XX-filename--> (see the example of a form generator invocation: Invocation).
HTML 5 Validation
The validation of forms is supported by imperia. The HTML attributes required as well as pattern have been extended:
You can add following parameters to the imperia FORM tag (which is included in every template) to define the behavior:
<!--formstart:VIEW=/layout/editmode/start_form.html:polyfill=sample:latch=verify-->
- VIEW: With this parameter you define the VIEW template where more parameters are interpreted. If you don't set this parameter,
/layout/edit-mode/start_form.html
will be used in the EDIT mode as well as/layout/editmode/start_multiple_form.htm
for Assets. All further paramters will be interpreted by these example templates. - polyfill: With this parameter you not only provide the forms but also the feature "HTML 5 validation" for older browsers.In order to activate polyfill, set this parameter to
sample
. By default, this feature is deactivated. - novalidate: When setting this parameter, all HTML5 validation in EDIT mode is deactivated. This feature is deactived by default.
- latch: The parameter latch defines whether a HTML5 form validation should be carried out when caching in EDIT mode. In order to acitvate this feature, set the value to
verify
. By default, this feature is deactivated. - autocomplete: When setting this parameter, the feature autocomplete will be activated in input fields. By default, this feature is deactived.
E-mail Action Configuration#
The following configuration options have to be specified in a document's meta information or within a template inside hidden input and input fields.
__form_generator_actions_email_recipient
Specifies a recipient e-mail address of the e-mails sent by this action.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_recipient" type="text"
value="recipient@mail.com"/>
__form_generator_actions_email_sender
Specifies a form field, which will contain the sender's e-mail address.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_sender" type="text"
value="sender@mail.com"/>
__form_generator_actions_email_subject
Specifies a form field, which will contain the e-mail's subject.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_subject" type="text"
value="email_subject"/>
__form_generator_actions_email_content
Specifies a form field, which will contain the e-mail text body.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_content" type="textarea"
value="email_content"/>
Note
Instead of using __form_generator_actions_email_content you can also use __form_generator_actions_email_html_view.
__form_generator_actions_email_html_view
Specifies a hidden form field, which contains the view-template for layouting the e-mail.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="__form_generator_actions_email_html_view" type="hidden"
value="/live/mail/html.html" >
__form_generator_actions_email_name
Specifies a form field, which will contain the name of the sender.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_name" type="text"
value="sender_name"/>
__form_generator_actions_email_relay
Specifies an e-mail relay. Defaults to “localhost”.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_relay" type="hidden"
value="localhost"/>
__form_generator_actions_email_header
Specifies a custom header to be added to the email. Multiple values are supported.
//WRAPPED FOR REPRESENTATION PURPOSES
<input name="IMPERIA:__form_generator_actions_email_header" type="text"
value="X-Generator: imperia VERSION (http://www.imperia.net)"/>
Form Generator Case Example (step by step)#
Step 1 - Configuration#
- In order for the form generator to work the forms should be enabled for the template processor (Menu > System > General Settings > Template processor > Allow forms).
- Set the SMTP-Server in the system.conf: SMTP_SERVER = your.domain.de
- Set the correct path to your custom views in the system.conf if neccessary: "VIEW_TEMPLATE_DIRS" = "/dir/www/your_imperia/dev/site/view/your_project/
Step 2 - Invocating the form generator from a Codeinclude-file#
1) //WRAPPED FOR REPRESENTATION PURPOSES
#IF (<!--XX-editmode-->)
<link rel="stylesheet" type="text/css" href="/assets/css/form_generator_edit_mode.css">
<input name="__form_generator_actions" type="hidden" value="email" />
<input name="__form_generator_actions_email_relay" type="hidden" value="localhost" />
<input name="__form_generator_actions_email_subject" type="hidden" value="subject" />
<input name="__form_generator_actions_email_sender" type="hidden" value="email" />
<input name="__form_generator_actions_email_name" type="hidden" value="name" />
<input name="__form_generator_actions_email_html_view" type="hidden" value="/live/mail/html.html" >
<!-- Formularfelder die der Viewprozessor nicht sehen soll -->
2) <input name="__form_generator_actions_email_discard_fields" type="hidden" value="honey_name" />
<input name="__form_generator_actions_email_discard_fields" type="hidden" value="honey_submit" />
<input name="__form_generator_actions_email_discard_fields" type="hidden" value="honey_email" />
<input name="__form_generator_actions_email_discard_fields" type="hidden" value="honey_homepage" />
<div class="container">
3) <div class="card">
<div class="card-header" role="tab" id="headingFormGenOne">
<label class="card-title">
<a role="button" data-toggle="collapse" href="#collapseFormGenOne" aria-expanded="true"
aria-controls=" collapseFormGenOne">
{% __('E-Mail-Empfänger/in für dieses Formular') %}
</a>
</label>
</div>
<div id="collapseFormGenOne" class="card-collapse collapse in" role="tabpanel"
aria-labelledby="headingFormGenOne">
<div class="card-block">
<div class="common-meta">
<input name="__form_generator_actions_email_recipient" value="yourmail@yourmail.de"
required="required" style="width: 200px; margin-left: 10px;" />
</div>
</div>
</div>
</div>
4) <!-- Formularfelder die der Viewprozessor nich sehen darf -->
<input name="__form_generator_skip_fields" type="hidden" value="honey_name" />
<input name="__form_generator_skip_fields" type="hidden" value="honey_email" />
<input name="__form_generator_skip_fields" type="hidden" value="honey_homepage" />
5) <div class="card">
<div class="card-header" role="tab" id="headingFormGenTwo">
<label class="card-title">
<a role="button" data-toggle="collapse" href="#collapseFormGenTwo" aria-expanded="true"
aria-controls="collapseFormGenTwo">
{% __('Bestätigungstext bei erfolgreichem Versand') %}
</a>
</label>
</div>
<div id="collapseFormGenTwo" class="card-collapse collapse in" role="tabpanel"
aria-labelledby="headingFormGenTwo">
<div class="card-block">
<div class="multilang-meta">
<?imperia iwe2
id: success_message
customConfig: /iwe2-customize.js
?>
</div>
</div>
</div>
</div>
6) <div class="card">
<div class="card-header" role="tab" id="headingFormGenThree">
<label class="card-title">
<a role="button" data-toggle="collapse" href="#collapseFormGenThree" aria-expanded="true"
aria-controls="collapseFormGenThree">
{% __('E-Mail-Betreff') %}
</a>
</label>
</div>
<div id="collapseFormGenThree" class="card-collapse collapse in" role="tabpanel"
aria-labelledby="headingFormGenThree">
<div class="card-block">
<div class="multilang-meta">
<input name="IMPERIA:subject" value="{% __('Anfrage über das Webformular') %}" required="required"
style="width: 300px; margin-left: 10px;" />
</div>
</div>
</div>
</div>
7) <div class="card">
<div class="card-header"role="tab" id="headingFormGenFour">
<label class="card-title">
<a role="button" data-toggle="collapse" href="#collapseFormGenFour" aria-expanded="true"
aria-controls="collapseFormGenThree">
Formular Konfigurator
</a>
</label>
</div>
<div id="collapseFormGenFour" class="card-collapse collapse in" role="tabpanel" aria-labelledby="headingFormGenFour">
<div class="card-block">
<strong>So verwenden Sie den Formulargenerator:</strong>
Ziehen Sie ein Textfeld und ein E-Mailfeld in den Formularbereich. Geben Sie unter den
Feldoptionen im Bereich "Name:" den Wert "name" für das Textfeld ein und im E-Mailfeld
unter "Name:" den Wert "email" ein. Aus diesen Feldern wird später der Name sowie die
E-Mailadresse des Versenders generiert
</br>
<div class="form_gen_container">
<div style="float:left;">
<?imperia form_generator
id:66
custom_fields:1
placeholder_polyfill:true
textdomain: net.imperia.www
?>
</div>
<div class="i-form-generator-field-drop" style="width: 30em; height: 52.5em;
border: 1px dotted #ddd; overflow:auto; margin-left: 40em; margin-top:0.5em">
<div style="font-style: italic;">
Formularfelder hier hereinziehen!
</div>
<input name="IMPERIA:my_fields_options" type="hidden" data-field-control="options" />
<input name="IMPERIA:my_fields" type="hidden" data-field-control="html"/>
</div>
</div>
<br style="clear: both;"/>
</div>
</div>
</div>
</div>
#ELSE
<div class="row">
8) <!--#if expr="$QUERY_STRING = /sent/"-->
<div class="container wow fadeInUp" data-wow-duration="0.80s">
<div class="text-center">
<div class="success_message">
<!--XX-success_message-->
</div>
</div>
</div>
<script>
$('#hide_element').css('display', 'none');
</script>
<!--#else-->
9) <div id="hide_element">
<div class="container forms">
<form action="/imp/document/form_generator_action" method="POST">
<input name="__form_generator_path" type="hidden" value="<!--XX-directory-->/<!--XX-filename-->" />
10) <!--Honeypot-Protection-->
<input name="honey_name" id="honey_name_<!--DOC_ID:%06x-->_0"
placeholder="{% __('Dieses Feld nicht ausfüllen! Anderenfalls wird das Formular nicht akzeptiert!') %}"
type="text" class="form-control form-hp" />
<input name="honey_email" id="honey_email_<!--DOC_ID:%06x-->_0"
placeholder="{% __('Dieses Feld nicht ausfüllen! Anderenfalls wird das Formular nicht akzeptiert!') %}"
type="email" class="form-control form-hp" />
<input name="honey_homepage" id="honey_homepage_<!--DOC_ID:%06x-->_0"
placeholder="{% __('Dieses Feld nicht ausfüllen! Anderenfalls wird das Formular nicht akzeptiert!') %}"
type="homepage" class="form-control form-hp" />
11) <div id="row1_form" class="i-form-generator-field-drop">
<?imperia form_generator
id:66
textdomain: net.imperia.www
custom_fields:1
placeholder_polyfill:true
?>
</div>
<input name="__form_generator_field_options" type="hidden" value="my_fields_options" />
12) <input name="__form_generator_success_uri" type="hidden" value='<!--#echo var="SCRIPT_NAME"-->?sent' />
<input name="__form_generator_error_uri" type="hidden" value='<!--#echo var="REQUEST_URI"-->' />
<div id="row1_form" class="i-form-generator-field-drop">
<div class="col-md-6 col-md-offset-3 wow fadeInUp" data-wow-duration="0.80s">
13) <!--XX-my_fields-->
<script>
$(function () {
$('.datepicker').datetimepicker();
});
</script>
</div>
</div>
14) <div class="form-group imperia-field imperia-field-submit">
<ul class="imperia-field-errors"></ul>
<div class="col-md-6 col-md-offset-3">
<input type="submit" value="{% __('Abschicken') %}" class="btn btn-default"
id="submit_<!--XX-directory-->/<!--XX-filename-->" name="submit" />
</div>
</div>
</div>
<br style="clear: both;"/>
</form>
</div>
</div>
#ENDIF
<!--#endif-->
#IF NOT(<!--XX-editmode-->)
<link rel="stylesheet" type="text/css" href="/assets/css/form_generator_save_mode.css">
<link rel="stylesheet" type="text/css" href="/res/form-generator/lib/css/bootstrap-datetimepicker.min.css">
<script src="/res/form-generator/lib/js/bootstrap-datetimepicker.min.js"></script>
<style>
.form-hp {
display: none !important;
}
</style>
#ENDIF
15) <!--postconvert:View-->
Note
Note that in the editmode the fields "E-Mail" and "Name" are mandatory. If this fields are not choosen by the editor, the recipient will receive a empty mail. The fields must have a "name"-attribute with the value "name" for the name-field and email for the mail-field.
- If the mail is successfully sent, the URL is extended with ?sent. The success-message will be shown and the form will be hidden.
- In this case the form_generator_action-script is called. Alternatively one can choose the cgi-bin-script Form Submission and Validation. It is required that the input field __form_generator_path is submitted with the form itself. That field must contain the path to the document
- Finally the honeypot-protection is completed.
- This invocation is necessary for displaying the choosen form elements.
- In this step the error- and request-URI are set.
- The choosen fields are generated.
- Here the submit-button is implemented in the Codeinclude. Therefore the submit-button of the view 'default_fields.html' can be deleted.
- The imperia-View-Language is rendered in this step.
Step 3 - Calling the Codeinclude in a Flexmodule.#
AUTHOR: IMPERIA
VALIDCODES: forms
DESCRIPTION: Form Generator
<!--CINCL:/yourproject/form_generator.htms-->
Step 4 - Layouting the E-Mail#
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Mail</title>
<style>
/* *********************************
CUSTOM STYLE
***********************************/
</style>
</head>
<body class="">
<h1>Anfrage über das Webformular</h1>
<table border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td> </td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<table class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
{% #foreach key (@{params.@keys}) %}
<tr>
<td><h3><strong>{% key %}</h3></strong></td>
</tr>
<tr>
<td>{% params[key] %}</br></td>
</tr>
<tr>
<td><hr /></td>
</tr>
{% #end %}
</tbody>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">Pirobase imperia GmbH</span>
</td>
</tr>
<tr>
<td class="content-block powered-by">
Powered by <a href="http://imperia.net">Imperia</a> form generator. / © 2016
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER --></div>
</td>
<td> </td>
</tr>
</table>
</body>
</html>
The userinput is sent as a key-value pair. The foreach-loop iterates over the keys and values and generates a table with the keys as table head and the values as table data.