Published by Mijingo

EE Insider

spacer

ExpressionEngine How-to Articles

Topics range from beginner to advanced, but are all born out of real world, professional, day-to-day use of ExpressionEngine. Need more information? Get training videos and ebooks on ExpressionEngine from Mijingo.

Reusable Form Templates with ProForm

by Isaac Raway

Editor Note: In this how-to article, ProForm developer Isaac Raway shows how to create reusable form templates with his ProForm module.

One of the features of ProForm is the ability to create a single template capable of rendering any form that is designed in the module. Creating a reusable form template is simple and it can provide the same consistent UI to all of your forms, reducing the amount of work it takes to create a new form.

Goals

The basic goals for this setup is to be as flexible as possible. To this end, the essential design for this system is intended to allow multiple ways of using the same base template:

  1. As a full form URL - this allows us to simply link to forms that have been created in ProForm, without having to hook up anything else
  2. As an embedded template - allows placing the form inside of another custom template that might also do other things
Setup

We will have a single template group to contain all the templates for our forms system:

  • forms

Within this template group, we will have these templates:

  • forms/index - allows loading forms directly from a URL.
  • forms/_layout - contains the actual form tag and custom logic.

Follow the next sections in order to create the group and its templates now.

Template Manager

The Template Manager is where you can create and edit templates in EE:

  1. Log into your control panel
  2. Click Design > Templates > Template Manager
Create The Template Group

Once inside the Template Manager, do these steps to create the template groups:

  1. On the left side of the Template Manager, click New Group.
  2. Enter “forms” as the Template Group Name, leave the other settings blank.
  3. Click Submit.
Create _Layout Template

The index template is automatically created for us.

Next, create the _layout template:

  1. Click Design > Templates > Template Manager.
  2. On the left side of the Template Manager, click on the forms Template Group.
  3. On the right side of the Template Manager, click New Template to create a template within this group.
  4. Enter _layout as the Template Group Name, leave the other settings blank.
  5. Click Submit.
Forms Index Template

Copy & paste the following code into the forms/index template.

{embed='forms/_layout' form_name='{segment_2}'

You can use the same embed tag in other templates in order to inject the template layout into other areas of the site.

Forms Layout Template

The _layout template actually calls our form tag, using the form_name provided either from the index template or wherever else we might use the embed template.

This template is based on the one that’s automatically rendered by the exp:proform:simple tag, which you may want to use instead. However, by using the full form tag in our embed template, we can easily make changes to how each field type is rendered.

Copy & paste the following code into the forms/_layout template:

{exp:proform:head} {!-- Include the default ProForm styling. --}
{exp
:proform:form form_class="proform {embed:form_name}_proform"
   
form_name="{embed:form_name}" variable_prefix="pf_"}

   {if pf_no_results}
       Invalid form name specified
!
   
{/if}
   
   {if pf_complete}
       Thank you 
for your submission!
   
{if:else}

   {pf_hidden_fields}
       
<input type="hidden" name="{pf_field_name}" value="{pf_field_value}" />
   
{/pf_hidden_fields}

   
<input type="hidden" name="_pf_current_step" value="{pf_current_step}" />
   <
input type="hidden" name="_pf_goto_step" value="" />

   
{if pf_multistep}
       
<ul class="pf_steps">
           
{pf_steps}
               
<li><a href="#{pf_step_no}" class="pf_step {pf_step_active}">{pf_step}</a></li>
           
{/pf_steps}
       
</ul>
   
{/if}

   
<div class="pf_wrap">

       
{pf_fieldrows}
       
<ul class="pf_row">
           
{pf_fields}
               {if pf_field_type 
!= "invisible"}
                   
<li id="{pf_field_html_id}" class="pf_column {pf_field_html_class}">
                   
{if pf_field_html_block}
                       {pf_field_html_block}
                   {if
:elseif pf_field_heading}
                       
<h3>{pf_field_heading}</h3>
                   
{if:else}
                       {if pf_field_type 
!= "checkbox"}
                           
<label for="{pf_field_name}">{pf_field_label} {if pf_field_is_required}<span class="required">*</span>{/if}</label>
                           <
div class="pf_field {if pf_vertical}pf_vertical{/if}">
                       
{/if}
                       {if pf_field_type 
== "string"}
                           {if pf_field_validation
:valid_email}
                               
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="validate-email {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                           
{if:else}
                               {if pf_field_length 
<= 255}
                                   
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="{pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                               
{if:else}
                                   {if pf_wysiwyg}
                                       
<textarea name="{pf_field_name}" id="{pf_field_name}" class="{pf_field_is_required}">{pf_field_value}</textarea>
                                       <
script type="text/javascript">bkLib.onDomLoaded(function() new nicEditor(pf_nic_config).panelInstance('{pf_field_name}'); });</script>
                                   {if
:else}
                                       
<textarea name="{pf_field_name}" id="{pf_field_name}" class="{pf_field_is_required}">{pf_field_value}</textarea>
                                   
{/if}
                               {
/if}
                           {
/if}
                       {if
:elseif pf_field_type == "text"}
                           {if pf_wysiwyg}
                               
<textarea name="{pf_field_name}" id="{pf_field_name}" class="{pf_field_is_required}">{pf_field_value}</textarea>
                               <
script type="text/javascript">bkLib.onDomLoaded(function() new nicEditor(pf_nic_config).panelInstance('{pf_field_name}'); });</script>
                           {if
:else}
                               
<textarea name="{pf_field_name}" id="{pf_field_name}" class="custom_class_here {pf_field_is_required}">{pf_field_value}</textarea>
                           
{/if}
                       {if
:elseif pf_field_type == "date"}
                           
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="date {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                       
{if:elseif pf_field_type == "datetime"}
                           
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="datetime {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                       
{if:elseif pf_field_type == "time"}
                           
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="time {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                       
{if:elseif pf_field_type == "integer"}
                           
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="validate-integer {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                       
{if:elseif pf_field_type == "float"}
                           
<input type="text" name="{pf_field_name}" id="{pf_field_name}" class="validate-float {pf_field_is_required}" value="{pf_field_value}" placeholder="{pf_field_placeholder}" />
                       
{if:elseif pf_field_type == "file"}
                           
<div class="pf_files">
                               <
input name="{pf_field_name}" id="{pf_field_name}" type="file" class="{pf_field_is_required}" />
                           </
div>
                       
{if:elseif pf_field_type == "checkbox"}
                           
<div class="pf_field">
                               <
div class="pf_option">
                                   <
input type="checkbox" name="{pf_field_name}" id="{pf_field_name}" value="y" {if pf_field_checked}checked="checked"{/if} class="{pf_field_is_required}" /><label for="{pf_field_name}">{pf_field_label}</label>
                               </
div>
                           </
div>
                       
{if:elseif pf_field_type == "list"}
                           
<select name="{pf_field_name}" id="{pf_field_name}" {if pf_multiple}multiple="multiple"{/if} class="{pf_field_is_required}">
                           
{pf_field_setting_list}
                               
<option value="{pf_key}" {pf_selected}>{pf_row}</option>
                           
{/pf_field_setting_list}
                           
</select>
                           
{if pf_field_style == "checkboxes"}
                               {pf_field_setting_list}
                               
<div class="pf_option {if pf_vertical}pf_vertical{/if}">
                                   <
input type="checkbox" name="{pf_field_name}" id=
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.