Form

The <ion:form /> tag manages forms.

With simple children tags, this tag :

  • Display the form
  • Display form validation messages (errors on fields, success)
  • Sends data to one form processing custom library

We will create one example form to illustrate this tag usage.
To create this form, we will need to:

  1. Declare and configure the form in the theme "forms" config file.
    Location of the config file : /themes/your_theme/config/forms.php
  2. Create one view containing the form (it can be a page view which displays other data from website)
    Location of the view: /themes/your_theme/views/contact.php
  3. Create your own Tagmanager library which will process the form data.
    Location of the library: /themes/your_theme/libraries/Tagmanager/Contact.php

Form children tags

The <ion:form /> tag is a little bit special : All its children tags must be used in the context of the wished form.

In other words, if one form called "my_form" in declared in the forms.php config file, all children tags will be used with the tag <ion:form:my_form /> as parent.

In this table, we consider one form called "my_form".

TagReturnsExample
<ion:form:my_form:validation /> Nothing.
Parent tag for the validation children tags
<ion:form:my_form:validation:success/>

Global validation success message.
Can be used in conditional mode.

<!-- Displays the validation success message -->
<ion:form:my_form:validation:success tag="p" class="green" />

<!-- Custom message by testing the result -->
<ion:form:my_form:validation:success is="true">
... this will be displayed if the validation succeed
</ion:form:my_form:validation:success>
<ion:form:my_form:validation:error/> Global validation error message.
Can be used in conditional mode.
<!-- Displays the validation error message -->
<ion:form:my_form:validation:error tag="p" class="red" delimiter="p" />
<!-- Custom message by testing the result -->
<ion:form:my_form:validation:error is="true">
... this will be displayed if the validation fails
</ion:form:my_form:validation:error>
<ion:form:my_form:validation:result/> Nothing.
Conditional tag to test validation result.
<ion:form:my_form:validation:result is="true">
... displayed if validation was done
</ion:form:my_form:validation:result>
<ion:form:my_form:posted />
Conditional tag to test if the form was posted.
<ion:form:my_form:posted is="false">
Please fill in our form...
<ion:form:my_form:posted>
<ion:form:my_form:field /> Parent field tag.
Used to refill the form fields after unsuccessful validation
<input type="text" name="firstname" value="<ion:form:my_form:field:firstname />" />
<ion:form:my_form:error />
Parent tag to display one given validation error
<!-- Display of one error message under the input if the validation failed -->
<input type="text" name="firstname" value="<ion:form:my_form:field:firstname />" />
<ion:form:my_form:error:firstname tag="p" class="input-error" />

Declare the formTop of Page

Create the file /themes/your_theme/config/forms.php with this content :

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/*
|--------------------------------------------------------------------------
| Theme Forms configuration
|--------------------------------------------------------------------------
|
| This forms config array will be merged with /application/config/forms.php
| You can overwrite standard forms definition by creating your own deifnition
| for the form you wish to overwrite.
|
*/
$config['forms'] = array
(
// Contact form
'contact' => array
(
// The method which will process the form
// The function name has no importance, it must only be in the declared Tagmanager class
// and be "public static"
'process' => 'TagManager_Contact::process_data',

// Redirection after process. Can be 'home' or 'referer' for the $_SERVER['HTTP_REFERER'] value.
// If not set, doesn't redirect
'redirect' => 'referer',

// Messages Language index, as set in language/xx/form_lang.php
'messages' => array(
'success' => 'form_message_success',
'error' => 'form_message_error',
),

// Form definition: fields and rules
'fields' => array
(
'name' => array
(
// CI validation rules
'rules' => 'trim|required|min_length[3]|xss_clean',
// Label translated index, as set in language/xx/form_lang.php
// Will be used to display the label name in error messages
'label' => 'form_label_name',
),
'company' => array(
'rules' => 'trim|required|xss_clean',
'label' => 'form_myform_label_company',
),
'email' => array(
'rules' => 'trim|required|valid_email|xss_clean',
'label' => 'form_label_email',
),
// Example of radio inputs : "You heard about our company on..."
'heard' => array(
// Can be 'radio', 'checkbox', 'select' or not set for input and textarea
'type' => 'radio',
'rules' => 'required',
'label' => 'form_label_heard_on',
)
)
),
);

Create the form's viewTop of Page

In the forms.php config file, we declared one form called "contact".

Create the file /themes/your_theme/views/contact.php with this content :

<h2>Contact form</h2>
<!--
Success message
Displayed if the form was successfully validated
-->
<ion:form:contact:validation:success tag="p" class="green" />

<!--
Error message
Displayed if the form doesn't pass the validation
the 'form_message_error' key is located in : themes/your_theme/language/xx/tags_lang.php
-->
<ion:form:contact:validation:error is="true" >
<span class="red">
Error : Some form data are missing or seem to be incorrect.
</span>
</ion:form:contact:validation:error>

<!--
Form has no action because the same page will process the data.
POST data are catched by the global Tagmanager and processed by the Tagmanager's library method 'process_data'
defined in : /themes/your_theme/libraries/Tagmanager/Contact.php
as declared in the form config file : /themes/your_theme/config/forms.php
-->
<form method="post" action="">

<!--
The form name must be set so the tags identify it.
Same name than the one declared in forms.php
-->
<input type="hidden" name="form" value="contact" />

<!--
Input : Name
-->
<label for="name">Name</label>

<!-- Fills again the user input in case of failed validation -->
<input type="text" id="name" name="name" value="<ion:form:contact:field:name />"/>

<!-- Displays the error linked to this input in the validation fails -->
<ion:form:contact:error:name tag="p" class="input-error" />


<!--
Input : Company
-->
<label for="company">Company</label>
<input type="text" id="company" name="company" value="<ion:form:contact:field:company />"/>
<ion:form:contact:error:company tag="p" class="input-error" />


<!--
Input : Email
-->
<label for="email">
Email<br/>
<span class="note">The form data will be send to this email address.</span>
</label>
<input type="text" id="email" name="email" value="<ion:form:contact:field:email />"/>
<ion:form:contact:error:email tag="p" class="input-error" />


<!--
Input : You heard about our company...
-->
<label>You heard about our company on...</label>

<div>

<!-- Fills again the user input in case of failed validation -->
<input type="radio" name="heard" id="heard-contact-facebook" value="Facebook" class="left" <ion:form:contact:radio:heard value="Facebook" /> />
<label for="heard-contact-facebook">
<ion:lang key="form_label_heard_facebook" />
</label>

<input type="radio" name="heard" id="heard-contact-friend" value="one very good friend" class="clear left" <ion:form:contact:radio:heard value="one very good friend" default="true" /> />
<label for="heard-contact-friend" >
<ion:lang key="form_label_heard_friend" />
</label>

<input type="radio" name="heard" id="heard-contact-website" value="another website" class="clear left" <ion:form:contact:radio:heard value="another website" /> />
<label for="heard-contact-website" >
<ion:lang key="form_label_heard_website" />
</label>

<ion:form:contact:error:heard tag="p" class="error" />
</div>

<!--
Submit button
-->
<input type="submit" value="Send the data" />

</form>

Process the formTop of Page

In the file /themes/your_theme/config/forms.php, we declare that the form wille be processed by the method "process_data" of the class "TagManager_Contact".

Create the file /themes/your_theme/libraries/Tagmanager/Contact.php and write the following code :

<?php
/**
 * Contact Form TagManager
 *
 */
class TagManager_Contact extends TagManager
{
    /**
     * Processes the form POST data.
     *
     * @param FTL_Binding
     *
     * @return void
     *
     */
    public static function process_data(FTL_Binding $tag)
    {
        // Name of the form : Must be send to identify the form.
        $form_name = self::$ci->input->post('form');

        // Because Form are processed before any tag rendering, we have to run the validation
        if (TagManager_Form::validate($form_name))
        {
            // Posted data
            // To see the posted array, uncomment trace($posted)
            // If you prefer to see these data through one log file,
            // uncomment log_message(...) and be sure /application/config/config.php contains :
            // $config['log_threshold'] = 1;
            // The log files are located in : /application/logs/log-YYYY-MM-DD.php
            // We prefer to log our 'dev' data as 'error' to not see the all CodeIgniter 'debug' messages.

            $posted = self::$ci->input->post();
            // trace($posted);
            // log_message('error', print_r($posted, TRUE));


// ... Here ... you do what you want with the data ...

            // Add one custom Success message
            // Get the messages key defined in : /themes/your_theme/config/forms.php
            // You can also set directly one lang translated key
            $message = TagManager_Form::get_form_message('success');
            TagManager_Form::set_additional_success($form_name, $message);

            // Alternative : Set the message by using directly one lang translated key :
            // TagManager_Form::set_additional_success($form_name, lang('form_message_success'));

            // Use of the 'redirect' option of the form config.
            // If no redirect after processing, the form data can be send again if the user refreshes the page
            // To avoid that, we use the redirection directive as set in the config file:
            // /themes/your_theme/config/forms.php
            $redirect = TagManager_Form::get_form_redirect();
            if ($redirect !== FALSE) redirect($redirect);
        }
        /*
        // Normally, nothing should be done here, because the validation process refill the form
        // and doesn't redirect, so the user's filled in data can be used to fill the form again.
        // Remember : If you redirect here, the form refill will not be done, as the data are lost
        // (no access to the posted data anymore after redirection)
        else
        {
            // ... Do something here ...
        }
        */
    }
}

Send emails after form processingTop of Page

If you want to send one email after form processing, you will also need to:

  • Create one email view.
    Location is up to you, but as convention, we put the emails views in the folder : themes/your_theme/mail/
  • Declare the email in /themes/your_theme/config/forms.php

Using this method is optional :
You can also directly send the emails you want in the process_data() method.

Declare the email

Edit the file /themes/your_theme/config/forms.php and add the key "emails" as following:

$config['forms'] = array
(
// Contact form
'contact' => array
(
'process' => 'TagManager_Contact::process_data',

'redirect' => 'referer',

'messages' => array(
'success' => 'form_message_success',
'error' => 'form_message_error',
),
'emails' => array
(
array
(
// Send the mail to the address filled in in the 'email' input of the form
                // Values can be :
                // - One plain Email address :
                // - 'form' to send it to the email of the form data
                // - 'site' to send it to the Email set in Ionize under Settings > Advanced > Email > Website
                // - 'contact' to send it to the Email set in Ionize under Settings > Advanced > Email > Contact
                // - 'info' to send it to the Email set in Ionize under Settings > Advanced > Email > Info
                // - 'technical' to send it to the Email set in Ionize under Settings > Advanced > Email > Technical
'email' => 'form',

// Subject : Translation item index of the subject
'subject' => 'mail_contact_subject',

// Used view : Located in /themes/your_theme/mail/contact.php
'view' => 'mail/contact',
),
),
'fields' => array
(
'name' => array
(
'rules' => 'trim|required|min_length[3]|xss_clean',
'label' => 'form_label_name',
),
'company' => array(
'rules' => 'trim|required|xss_clean',
'label' => 'form_myform_label_company',
),
'email' => array(
'rules' => 'trim|required|valid_email|xss_clean',
'label' => 'form_label_email',
),
'heard' => array(
'type' => 'radio',
'rules' => 'required',
'label' => 'form_label_heard_on',
)
)
),
);

Create the email view

This view will be used as template for the email.

Create the file themes/your_theme/mail/contact.php :

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><ion:data:subject /></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="<ion:current_lang />" />
</head>
<body>

<table border="0" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="bg_fade">
<table border="0" width="880">
<tr>
<td>
<!--
Dear %s,
-->
<h1><ion:data:lang key="mail_contact_dear" swap="data::name" /></h1>

<!--
Message
Important : to swap text in the translated string, the 'lang' tag must be called
with the 'data' tag as parent.
-->
<p><ion:data:lang key="mail_contact_message" swap="global::site_title, data::heard, data::email" autolink="false"/></p>

<p><ion:lang key="mail_contact_message2" /></p>

<p>
<ion:lang key="form_label_name"/> : <b><ion:data:name /></b>, <br/>
<ion:lang key="form_label_company"/> : <b><ion:data:company /></b> <br/>
<ion:lang key="form_label_email"/> : <b><ion:data:email /></b> <br/>
</p>

<p>
<ion:lang key="mail_contact_thanks" swap="global::site_title" />
</p>

</td>
</tr>
</table>
</td>
</tr>
</table>

</body>
</html>


Modify the TagManager_Contact process() method

Edit the file /themes/your_theme/libraries/Tagmanager/Contact.php and add the call to TagManager_Email::send_form_emails() :

<?php
/**
* Contact Form TagManager
*
*/
class TagManager_Contact extends TagManager
{
/**
* Processes the form POST data.
*
* @param FTL_Binding
*
* @return void
*
*/
public static function process_data(FTL_Binding $tag)
{
$form_name = self::$ci->input->post('form');

if (TagManager_Form::validate($form_name))
{
$posted = self::$ci->input->post();


// ... Here ... you do what you want with the data ...


// Send the posted data to the Email library and send the Email
// as defined in /themes/your_theme/config/forms.php
TagManager_Email::send_form_emails($tag, $form_name, $posted);


$message = TagManager_Form::get_form_message('success');
TagManager_Form::set_additional_success($form_name, $message);

$redirect = TagManager_Form::get_form_redirect();
if ($redirect !== FALSE)
redirect($redirect);
}
}
}

Explanation

To send the form declared emails, we called TagManager_Email::send_form_emails($tag, $form_name, $posted);

This method receives the form name ($form_name) and the posted data ($posted) and send each email as declared in the "emails" key of the forms.php config file.

In the view, the form posted data are available with the tag <ion:data />

Email view and language translated terms

The email view displays translated sentences, and "swaps" inside them the data received by the form.
For example :

<h1><ion:data:lang key="mail_contact_dear" swap="data::name" /></h1>

... retrieves the translation term key "mail_contact_dear" and replaces %s by the field "name" filled up in the form.

The lang file /themes/your_theme/languages/xx/form_lang.php contains :

<?php

// Translated strings used in the contact form sent email
$lang['mail_contact_subject'] = 'Thanks for your interest on %s';
$lang['mail_contact_dear'] = 'Dear %s,';
$lang['mail_contact_message'] = 'You heard about <b>%s</b> through <b>%s</b> and we thank you very much for your interest. Your email is %s.';
$lang['mail_contact_message2'] = 'Here are the data you just send us:';
$lang['mail_contact_thanks'] = 'The whole team of <b>%s</b> thanks you.';

It is possible to get translated sentences containing more than one data :

<ion:data:lang key="mail_contact_message" swap="global::site_title, data::heard, data::email" autolink="false"/>

In this case, we see that we swapped 3 data in the string "mail_contact_message".
We also said to the tag it must not create links with emails.