Rendering forms
Introduction
The form tag is built so you can take over one layer at a time. Each step below keeps everything from the step before that you did not replace. The examples render the same Contact Us form on a real install, and the output beside each template is what came back.
1. One tag, no markup
With no markup between the tags, the form renders from its theme: the <form> element, the hidden meta block, the success and error notices, the pages, sections and fields, and each page's buttons.
The whole form from the theme
Example{exp:formidable:form form_handle="contact_us"}
<form id="contact_us" name="contact_us" method="post" action="https://example.com/index.php?ACT=101" data-formidable-disable-submit="1">
…
<div class="formidable-form-content"><div class="formidable-page mb-8" data-formidable-page="1" data-formidable-page-id="p_1">
<div class="formidable-section mb-6" data-formidable-section="s_1_1" data-formidable-page="1">
<div class="grid grid-cols-1 gap-6 lg:grid-cols-12">
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="first_name">First Name</label>
<span class="formidable-field-instructions text-sm text-grey-300" id="first_name-instructions">We prefer your legal name</span>
…
<div class="formidable-page-nav mt-4 flex items-center justify-end gap-2" data-formidable-page-nav="1">
<button type="submit" class="formidable-button rounded-md bg-indigo-600 px-4 py-2 text-white" data-formidable-page-submit="">Submit</button>
</div>
</div>
</div>
</form>
Use this when the theme's markup suits you. You can still change classes and attributes from the control panel or the tag. See Regions and attributes.
2. Your own <form>, the theme's fields
Write the <form> element yourself and Formidable stops writing its own. It notices the literal <form in your template. Keep {form_attributes} on it: it carries the action URL, the method, and enctype="multipart/form-data" when the form has a file field. Without that, uploads are silently dropped.
{form_meta} places the hidden inputs. If you forget it, Formidable adds them straight after your opening <form> tag. Inside {fields}, {field_template} renders each field from the theme.
Your <form>, theme fields
Example{exp:formidable:form form_handle="contact_us"}
<form {form_attributes}>
{form_meta}
{form_error_summary}
{fields}
{field_template}
{/fields}
<button type="submit">Send</button>
</form>
{/exp:formidable:form}
<form id="contact_us" name="contact_us" method="post" action="https://example.com/index.php?ACT=101" data-formidable-disable-submit="1">
…
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="first_name">First Name</label>
<span class="formidable-field-instructions text-sm text-grey-300" id="first_name-instructions">We prefer your legal name</span>
<input id="first_name" name="first_name" value="" type="text" aria-describedby="first_name-instructions" class="block w-full rounded-md border border-gray-300 px-4 py-2 shadow-sm">
</div>
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" data-formidable-field="last_name" data-formidable-conditions-show='[{"boolean":"and","handle":"first_name","operator":"is_not_empty"}]' data-formidable-conditions-mode="show" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="last_name">Last Name</label>
<input id="last_name" name="last_name" value="" type="text" class="test-class block w-full rounded-md border border-gray-300 px-4 py-2 shadow-sm">
</div>
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="email_address">Email Address</label>
<input id="email_address" name="email_address" value="" type="email" class="block w-full rounded-md border border-gray-300 px-4 py-2 shadow-sm">
</div>
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="birthday">Birthday</label>
<input id="birthday" name="birthday" value="" type="date" class="block w-full rounded-md border border-gray-300 px-4 py-2 shadow-sm">
</div>
<div data-formidable-columns="12" data-formidable-page="1" data-formidable-section="s_1_1" data-formidable-field="parent_guardian_name" data-formidable-conditions-show='[{"boolean":"and","handle":"age","operator":"less_than","value":"18"}]' data-formidable-conditions-mode="show" class="col-span-1 flex flex-col space-y-1 lg:col-span-12">
<label class="formidable-field-label font-semibold" for="parent_guardian_name">Parent/Guardian Name</label>
<input id="parent_guardian_name" name="parent_guardian_name" value="" type="text" class="block w-full rounded-md border border-gray-300 px-4 py-2 shadow-sm">
</div>
<button type="submit">Send</button>
</form>
The form's other fields render the same way. A plain {fields} loop has no pages, so your own <button type="submit"> ends the form. On a multi-page form, use {form_layout} to keep the page navigation.
3. Write your own field markup
Inside {fields}, every field's parts are available: {field_name}, {field_handle}, {field_instructions}, {field_attributes} for the input, {field_has_error} and {field_error}. only= limits the loop to the fields you name.
Hand-written field markup
Example{exp:formidable:form form_handle="contact_us" only="first_name|email_address"}
<form {form_attributes} class="stack">
{form_meta}
{fields}
<div class="field">
<label for="{field_handle}">{field_name}</label>
{if field_instructions}
<p class="hint" id="{field_handle}-instructions">{field_instructions}</p>
{/if}
<input {field_attributes}>
{if field_has_error}<p class="field-error">{field_error}</p>{/if}
</div>
{/fields}
<button type="submit">Send</button>
</form>
{/exp:formidable:form}
…
<div class="field">
<label for="first_name">First Name</label>
<p class="hint" id="first_name-instructions">We prefer your legal name</p>
<input id="first_name" name="first_name" value="" type="text" aria-describedby="first_name-instructions">
</div>
<div class="field">
<label for="email_address">Email Address</label>
<input id="email_address" name="email_address" value="" type="email">
</div>
<button type="submit">Send</button>
</form>
Two things are still Formidable's:
{field_attributes}carries the input'sid,name,type,value(repopulated after a failed submission),required, any saved attributes, and the accessibility attributes.aria-describedby. Because the field has instructions, the input points atfirst_name-instructions. When you print the instructions yourself, give that element the id{field_handle}-instructions, as above, so the reference resolves.
For fields with choices, loop over {field_options}:
{if field_group == "options"}
<select {field_attributes}>
{field_options}
<option value="{value}"{if selected} selected{/if}>{label}</option>
{/field_options}
</select>
{if:else}
<input {field_attributes}>
{/if}
4. Place individual fields by hand
Every field is also available outside the loop, by its handle. This suits a design where fields sit in very different places. Exclude them from the loop so they do not render twice:
{exp:formidable:form form_handle="contact_us" exclude="email_address"}
<form {form_attributes}>
{form_meta}
<div class="hero-signup">
<label for="email_address">Your email</label>
<input {field:email_address:attributes}>
{if error:email_address}<p class="field-error">{error:email_address}</p>{/if}
</div>
{fields}{field_template}{/fields}
<button type="submit">Send</button>
</form>
{/exp:formidable:form}
See Named fields for every {field:HANDLE:…} variable.
5. Show errors and success
After a failed submission the form renders again with errors. Every field is repopulated with what was typed. After a successful one, a form that returns to its own page shows a success notice once.
{exp:formidable:form form_handle="contact_us"}
<form {form_attributes}>
{form_meta}
{form_success_notice}
{form_error_summary}
{fields}{field_template}{/fields}
<button type="submit">Send</button>
</form>
{/exp:formidable:form}
{form_error_summary} and {form_success_notice} render nothing when there is nothing to say. To write them yourself, use {if form_has_errors} with the {form_errors} loop, and {if form_success} with {form_success_message}. The form tag reference has both in full.
Which layer to choose
| You want | Use |
|---|---|
| The theme's markup, perhaps with different classes | Step 1, with classes set in the control panel or region parameters |
| Your own page structure around the theme's fields | Step 2 |
| Complete control of every element | Step 3 or 4 |
| The same markup for every form on the site | A copied theme rather than per-template markup |