Form Builder

Build forms without code — with file uploads, reCAPTCHA and a log of every submission.

1
  • 61 ratings
  • 43 reviews
  • 1,827 projects
$20

Product support

Visit this product's website for support.

Categories

Form Builder

Build forms without code — with file uploads, reCAPTCHA and a log of every submission.

Form Builder Plugin

Build forms for your October CMS site without code — with file uploads, reCAPTCHA and a log of every submission.

Demo URL: https://october-demo.renatio.com/backend/backend/auth/signin
Login: formbuilder
Password: formbuilder

Contact forms, quote requests, job applications or surveys: put the form together from ready field types, place it on a page, and every submission lands in your inbox and in the backend.

Features

  • Build and manage forms in the October CMS backend, reorder fields with drag and drop
  • Live preview in a side panel of the form editor, at desktop or phone width, submittable without sending mail or writing a log
  • 28 field types out of the box, including repeater, signature, geolocation and page breaks, each with editable HTML markup, plus custom field types
  • Custom form template with the form_field() helper for any layout
  • Native AJAX file uploads with attachments in the submission and in the mail
  • Google reCAPTCHA v2 and v3, Cloudflare Turnstile and Spam Protection Plugin support
  • Reply-to and autoresponder with their own mail templates
  • Conditional fields, multi-page forms, live validation and prefill from the query string
  • Webhooks posting each submission as signed JSON
  • Bootstrap 5 and Tailwind CSS markup presets
  • Form submissions log with e-mail preview, filters, CSV/JSON export and automatic pruning
  • Import and export of forms and field types
  • Granular backend permissions for forms, field types and submissions
  • Events to override the form, the fields, the submitted data and the message
  • Forms, fields and field types translated per site with the translations built into October CMS
  • RainLab Location and RainLab Pages (form as a snippet) support
  • Multilingual: English, Polish, German, French, Spanish, Brazilian Portuguese, Italian, Russian, Dutch and Czech translations included — more available on request

Requirements

This plugin requires October CMS 4.4 or newer and PHP 8.2 or newer.

If you are running October CMS 4.0–4.3, use the 5.x version of this plugin, and on October CMS 3.x the 4.x version.

Why is this a paid plugin?

Something that is free has little or no perceived value. Users do not commit to free products and only use them until something else that looks nice and is free comes along. When I invest my time in the development of a new plugin I commit to supporting and maintaining it. I ask my customers to do the same. I do not make money from this plugin by advertisements, upgrades or additional services like hosting or setup.

Did you know that 30% of your purchase or donation goes to help fund the October Project?

My plugins take many hours to develop (40-120+) and even more hours to document and maintain. My paid plugins have to pay for both this time, and the time I am spending on free plugins and less successful paid plugins. This means that it will take even a successful plugin years to become profitable. Please consider buying an extended license if you want me to continue to maintain these plugins for the very small fee I ask in return or hire me for adding functionality that you feel is missing but valuable.

Like this plugin?

If you like this plugin, give this plugin a like or make a donation with PayPal.

My other plugins

Please check my other plugins.

Support

Please use GitHub Issues Page to report any issues with the plugin.

Reviews should not be used for getting support or reporting bugs, if you need support please use the Plugin support link.

Icon made by Darius Dan from www.flaticon.com.

Forms list in the Form Builder backend showing the mail template and field count of each form.

Installation via Command Line

php artisan plugin:install Renatio.FormBuilder

Documentation

Usage

After installation the plugin registers the Form Builder backend menu with four items: Forms, Field types, Form submissions and Settings. Two example forms are installed: a simple contact form and a default form with the basic field types.

Place the renderForm component on a CMS page, inspect it and choose the form.

The form is submitted through the AJAX Framework, so the layout must load it next to the page styles:

<head>
    {% styles %}
</head>
<body>
    ...
    {% framework extras %}
    {% scripts %}
</body>

Example of placing form component on CMS page

/themes/demo/pages/contact.htm

url = "/contact"
layout = "default"

[renderForm contactForm]
formCode = "contact-form"
==
{% component 'contactForm' %}

Example of placing form component on CMS partial

/themes/demo/pages/contact.htm

url = "/contact"
layout = "default"

[renderForm contactForm]
formCode = "contact-form"
==
{% ajaxPartial "contact" %}

/themes/demo/partials/contact.htm

{% component 'contactForm' %}

Important note: The form handler works only inside {% ajaxPartial %}, not inside a plain {% partial %}.

Forms

E-mail

Choose a Mail Template in the Recipients tab to mail each submission; a form with a template needs at least one recipient. Without a template nothing is mailed and every submission is logged. Pick the reply-to and autoresponder fields in the E-mail tab once the form is saved with its fields.

Live preview

Press Preview at the top of a saved form to open it in a side panel over the editor, rendered by the theme in the locale of the site selected in the backend, at desktop or 390 px phone width. It reloads after the form is saved and after a field is added, edited, deleted, reordered or hidden, so only unsaved changes in the main form are missing.

Submitting from the preview runs the validation and shows the success message, but sends no e-mail, calls no webhook, writes no submission log and follows no redirect. The panel needs the Update forms permission.

The theme's default layout is used; when the theme has more layouts, pick another one, or none, in the panel's toolbar.

The preview is a close approximation, not the live page: it is served from the backend, so the cms.page.* events run but the frontend route middleware does not. In particular the Spam Protection checks (honeypot, timing, blocked submissions) are skipped there, so test them on a real page.

Spam Protection

Install the Spam Protection Plugin to protect every Form Builder form with a honeypot, content rules, a single-use form token and a per-visitor rate limit. It works out of the box.

A submission identical to one accepted within the last minute is answered with the success message but is neither logged nor mailed again, so a double click or a page refresh after sending does not produce duplicates.

Custom template

The plugin generates the form template while the Custom Template field is empty. To replace that markup, write your own template there and render each field with the form_field() function, which takes the field name. The tab appears once the form is saved.

A visible field the template leaves out is not validated, logged or mailed, and saving the form or a field lists such fields. A Logged in user field is always saved and a captcha always stays required. A field written as its own <input name="...">, or a template printing form.fields, keeps every field as before.

Example that will display two fields in one row:

<div class="row">
    <div class="col-6">{{ form_field('first_name') }}</div>
    <div class="col-6">{{ form_field('last_name') }}</div>
</div>

The names of the form's own fields are listed above the editor; clicking one inserts its form_field() call at the cursor. The list follows the Fields tab, so a field added, renamed or deleted there shows up at once. In the editor, type {{ or press Ctrl+Space for the same fields, the form object, Twig filters and tags.

Floating labels

Turn on Floating labels in the form's Options tab to render Bootstrap floating labels. The theme must use Bootstrap 5 and the field types the Bootstrap 5 markup preset; other presets ignore the option.

Prefill from query string

Turn on Prefill from query string in the form's Options tab to fill fields from URL parameters of the same name, for example a campaign link /contact?subject=Offer&email=jan@example.com. It is off by default.

A parameter that matches no field is ignored, values longer than 255 characters are cut, and checkbox, geolocation, repeater, file upload, signature, captcha, submit, section and page fields are never prefilled. Hidden fields are, so a link can carry UTM or campaign identifiers; treat them as visitor input, like any posted value. The fields set as the autoresponder or reply-to e-mail are never prefilled either, so a crafted link cannot redirect a copy of the submission. The value replaces the field's default value literally (it is not translated), and the markup escapes it like any other default. Country and state selects ignore it, because their markup renders the selected option itself.

Live validation

Turn on Live validation in the form's Options tab to check a field as soon as the visitor leaves it. The check runs on the server with the same rules and messages as the submission, so a field never passes here and fails there. Nothing is logged and no email is sent. A field the visitor has not filled in yet is left alone until it has a value or has already failed once, file, captcha and hidden fields are only checked on submission, and a field its conditions hide is not checked at all. An error stays until the server clears it, and fixing a field also rechecks the failed fields whose rules refer to it, such as same:email. The check sends only the form's own fields, so Spam Protection does not count it as a submission and the form's single-use token stays valid.

Webhooks

Add an address in the form's Webhooks tab to have every submission posted there as JSON, without writing a listener in PHP. The body is:

{
    "id": "9d3f6c1e-8b2a-4f57-a1c4-2e6b0d7f5a93",
    "form": {"code": "contact-form", "name": "Contact Form"},
    "data": {"email": "john@example.com", "email_raw": "john@example.com"},
    "submitted_at": "2026-09-13T09:41:02+00:00"
}

data holds the submitted values under the field names, each also as <name>_raw with the value as it was posted. File upload fields are not included. It is the same data the mail gets, after formBuilder.extendFormData, so a field a listener removes from the mail is not sent to a webhook either, and a submission formBuilder.beforeSendMessage cancels is neither mailed, logged nor sent to a webhook. Turn on Send the visitor's IP address to add an ip key; it is off by default, as the address is personal data.

id is unique to each call and is also sent in the X-Webhook-Id header. A queued call that is retried keeps its id, so the receiver can drop a delivery it has already processed.

With a Signing secret the body is signed with HMAC-SHA256 and the signature is sent in the X-Signature header, so the receiver can tell a genuine call from a forged one. The secret is stored encrypted with the application key:

hash_equals(
    hash_hmac('sha256', file_get_contents('php://input'), $secret),
    $_SERVER['HTTP_X_SIGNATURE'] ?? ''
);

The signature covers the body alone, so a captured call stays valid if it is replayed. Reject a call whose submitted_at is not recent when that matters to you.

The address must be https and public: private and reserved ranges (IPv4 and IPv6), localhost, *.local, *.internal, *.home.arpa, single-label names and shorthand IPv4 forms such as 127.1 are refused. The check runs again right before each call, and the call goes only to the addresses it approved, so a name repointed inside the network is not followed, and neither is a redirect.

A webhook that fails or does not answer within 5 seconds never changes what the visitor sees; the failure is logged under Settings → Logs with the scheme and host only, as the path often carries a token. Send through the queue is on by default and makes up to three attempts, 10 and 60 seconds apart, after a timeout, a lost connection, a 5xx, 408 or 429. Without a queue worker (sync driver) the calls run inline and in parallel, and a slow DNS server holds the submission, because PHP has no timeout for the lookup.

Return false from formBuilder.beforeSendWebhook to drop a call (see Events).

A form export carries its webhooks without the signing secret. Imported back into the same installation, a webhook keeps its secret; on another installation set it again, as the import report reminds you.

Fields

Custom HTML markup for fields

The default markup of every field type uses Bootstrap 5 form classes. For a Tailwind CSS theme, switch to the Tailwind preset (see below). On a theme with another CSS framework, or none, change the HTML markup of each field type under Form Builder → Field types. The recommended approach is to duplicate the field type and modify the copy.

Markup presets

A preset is a set of field type templates for one CSS framework. The plugin ships Bootstrap 5 (the default) and Tailwind CSS. To switch, open Form Builder → Field types, press Restore system fields and pick the preset. The markup of every system field type is replaced with the preset's; field types you created or duplicated are left alone. The Restore markup to default button of a single system field type offers the same choice.

The presets differ only in CSS classes. Field IDs, data-* attributes and ARIA attributes the plugin's JavaScript relies on are the same, and the Tailwind preset styles an invalid field through the aria-invalid: variant. Floating labels are a Bootstrap feature, so the Tailwind preset ignores that form option. The preset files hold markup only: the reCAPTCHA v3 and Turnstile scripts live in the plugin's form.js and find their fields by the data-recaptcha-sitekey attribute and the formbuilder-turnstile class, so keep those in markup you write yourself.

The preset of the last restore is remembered: the restore dialog offers it first, and field types added by later plugin updates are created with its markup.

Tailwind CSS generates only the classes it finds in files, and the markup of field types is stored in the database. Point Tailwind (v4) at the preset files in the theme's stylesheet:

@import "tailwindcss";
@source "../../plugins/renatio/formbuilder/presets/tailwind";

The path is relative to the stylesheet, so adjust the number of ../ to where it sits. Classes you add by hand in the backend — to a field type's markup or to a field's CSS classes and Wrapper CSS classes — are not in those files; list them with @source inline("...") or in a file under @source, or Tailwind will leave them out.

Field types carry no outer margin, so a new form's CSS classes (Options tab) start with the spacing of the preset last restored: row g-3 for Bootstrap 5, space-y-4 for Tailwind CSS.

The form's own wrappers still use Bootstrap classes where Bootstrap has them: the seeded demo forms set wrapper classes such as col-md-6, and the success and error messages of the component are Bootstrap alerts. Change the wrapper classes of the fields and override the component's message.htm partial in the theme when using Tailwind.

To add a preset of your own, create presets/<name>/ in the plugin with one <field_type_code>.htm file per field type, for example presets/bulma/text.htm. It appears in the restore dialog without any code change; a field type with no file in the preset keeps its markup. Files added inside the plugin directory are overwritten by plugin updates, so keep a copy.

Custom field types

Create a field type under Form Builder → Field types with the New field type button. For example, an Email field type is the markup of Text with the input type changed to email. Once saved, it can be used in any form.

The markup is Twig with the variables below. They are listed above the editor — click one to insert it — and suggested as you type {{ or press Ctrl+Space, together with Twig filters and tags.

Property Type Description
label String Label for the field.
field_id String Unique field ID useful when pairing labels with inputs.
required Bool Whether the validation rules include required or accepted.
label_class String Label CSS classes.
name String HTML name attribute. Also used in mail template.
default String Default value for the field.
comment String Help block for the field.
class String HTML class.
wrapper_class String HTML wrapper class.
placeholder String Placeholder for the field.
options Array Options for dropdown, radio list, checkbox list.
custom_attributes String Custom HTML attributes. For example id="my-field".
field Array All attributes of the field record, for example field.id.
settings Array Public captcha settings, for example settings.site_key.
location_plugin_enabled Bool Whether RainLab.Location is installed.
has_floating_labels Bool Whether the form uses floating labels.
has_multiple_files Bool Whether a file upload field accepts several files.
messages Array Translated texts of the geolocation, signature, page and repeater fields, for example messages.signature.label.
rows Array Repeater rows rendered at start, each with index, number, label and html.
row_template Array Repeater row cloned for each added row, with __index__ and __number__ placeholders.
min_items Int Minimum rows of a repeater.
max_items Int Maximum rows of a repeater (50 when empty).

Conditional fields

A field can show or hide itself depending on what the visitor answered in other fields — the classic case being an Other option in a dropdown that reveals a textarea. Open the field's Conditions tab and choose:

  • Action — Show this field when or Hide this field when the conditions are met,
  • Match — whether all conditions or any condition has to be met,
  • the conditions themselves: another field, an operator (is equal to, is not equal to, contains, is empty, is not empty) and a value. For a dropdown or a list the value is the option key, not its label.

An empty, unchecked or missing field has no value at all, so test it with is empty / is not empty rather than is equal to an empty value. A field hidden by its conditions no longer counts as answered, so the fields that depend on it are evaluated as if it were empty.

Inputs of a hidden field are disabled in the browser, so their values are never submitted. The server evaluates the same conditions, drops whatever a hidden field still sent (including uploaded files) before validation, and skips its validation rules — a required rule on a field the visitor cannot see does not block the form, and its value never reaches the submission log, the e-mails or formBuilder.* listeners. reCAPTCHA and Turnstile fields ignore conditions and are always validated.

Conditions work with custom field types without editing their markup — the rendered field is wrapped in a <div data-field-conditions> with display: contents, so it does not affect a grid layout. Renaming a field updates the conditions that refer to it; a condition may only refer to a field of the same form.

Validation

Every field carries its own rules in the Validation tab, one per row, in the Laravel syntax — required, max:255, regex:/^\d+$/. The rule field suggests the rules the installation supports, including those other plugins register. Leave the message empty to use the built-in wording.

Saving a field is refused when a rule does not exist, misses its parameters, carries a broken regular expression or points exists/unique at another database connection, so those mistakes never reach the front end. Rules registered outside the backend request — a Validator::extend() call in CMS page code, for example — are unknown there, and a field using one cannot be saved.

A fresh install seeds the Contact Form and Default Form with the recommended set (an upgrade only adds the length limits to seeded fields whose rules were never changed):

Field type Rules
Text, Subject required, max:255
E-mail required, email, max:255
Phone number max:30
URL required, url, max:255
Numeric required, numeric
Date, Datetime required, date
Time required, date_format:H:i,H:i:s
Textarea required, max:5000

A length limit on every text field is what keeps a form from accepting a megabyte of text, so add one even where the value is optional.

Accessibility

The default field types link labels, help text and validation errors to the field, mark fields with a required or accepted rule as required, and group checkbox and radio lists in a fieldset. Add autocomplete through Custom attributes on fields that collect personal data, for example autocomplete="email".

Available field types

Field type Renders
Text a single-line text input
Textarea a multi-line text box
E-mail, Phone number, URL, Numeric an email, tel, url or number input
Date, Time, Datetime a date, time or datetime-local input
Color Picker a color input
Dropdown a dropdown with the given options
Checkbox a single checkbox
Checkbox List a list of checkboxes
Radio List a list of radio options, where only one can be selected
Hidden a hidden input
Logged in user see below
Section a heading and subheading for grouping fields
Page break, Page progress see below
Repeater see below
Submit the submit button
Geolocation, Signature, reCaptcha, Turnstile, File upload, Country select, State select see below

Logged in user

The Logged in user field type saves an attribute of the signed-in visitor with the submission — their address, name or id — without showing an input. Pick the attribute in Logged in user attribute on the field's Attributes tab; it defaults to email. Only these attributes can be picked: id, email, username, login, first_name, last_name, full_name, company, phone and created_at (saved as Y-m-d H:i:s). Anything else on the user model - password, persist and activation codes, IP addresses, notes - is never read. company and phone stay empty unless a plugin adds those columns to the user.

The value is read from the session when the form is submitted and replaces whatever the request carried under the field's name, so it cannot be changed by whoever posts the form, and conditions, validation, the log, the mail and every formBuilder.formSubmitted listener reading post() see the same value. With nobody signed in, or without RainLab.User installed, it is empty.

Give the field a required validation rule to accept the form only from someone signed in: the rule is checked against the value the server resolved, so it fails exactly when nobody is. The field renders only the element that shows this validation message, so set a message that tells the visitor to sign in.

Leave Visible on. An invisible field is dropped from the form altogether and then records no value.

For the same reason the field ignores conditions, cannot be the field another field's conditions test, and is never prefilled from the query string.

Geolocation

Renders a read-only input with a button that asks the browser for the coordinates of the visitor. Nothing is read without the visitor pressing the button and allowing access in the browser prompt.

The submission and the mail carry the coordinates together with a link to the place on OpenStreetMap:

52.2297, 21.0122 (https://www.openstreetmap.org/?mlat=52.2297&mlon=21.0122)

The _raw value is the bare latitude,longitude pair, which is what you want when the mail template builds a link of its own. Form Builder checks the value on every submission and empties anything that is not a pair of coordinates on the globe, so the log, the mail, the webhooks and the validation rules all see the same checked value.

  • The coordinates are shown in a read-only input next to the button, so the visitor sees what is being submitted.
  • The browser is asked for a regular, not a high-accuracy position, and the coordinates are rounded to 4 decimal places, which is about 11 m - close enough for an address without pinpointing the visitor.
  • The field is never prefilled, neither from its Default value nor from the query string, so only a location the visitor shared is ever submitted.
  • Add required to the validation rules to insist on a location. A visitor who refuses the browser prompt can still submit the form as long as the field is not required.
  • The button label and the status messages come from the plugin translations, so the markup stays the same in every language.

Note: Browsers only expose the location over HTTPS.

Signature

Renders a canvas the visitor signs with a mouse, a pen or a finger, plus a button clearing it. The drawing is saved as a PNG attached to the submission, exactly like an uploaded file: it shows under Attachments in the form submission and is attached to the mail unless Send uploaded files as mail attachments (Upload Options tab) is unchecked. Deleting the submission deletes the file.

The field carries no value in the mail template — {{ name }} is empty, because the signature is a file rather than text.

  • Add required to the validation rules to insist on a signature. An untouched canvas, and a drawing the plugin refuses, both fail that rule rather than going through as an empty submission.
  • Drawings over 256 KB and anything that is not a PNG are rejected, so a payload put into the hidden input by hand never reaches the disk.
  • The file is stored as a protected attachment, unlike an uploaded file, so it is not served from a public URL.
  • The height of the canvas is a style attribute in the field type markup; change it there for a taller signature box.

Accessibility: a signature needs a pointer — mouse, pen or finger — so the field cannot be completed with a keyboard alone. Do not make it the only way to finish a form that has to be usable without one; offer a second route (a typed name, a call back) alongside it.

Page break and Page progress

Two fields splitting a long form into pages the visitor moves through without the page reloading. Everything is still submitted in one request at the end, so nothing changes for the mail template or the submission log.

Put a Page break field wherever the form should be cut. It renders the Previous and Next buttons and hides the one that has nowhere to go, so two breaks give three pages. Set the field's Label for the text on the Next button and its Placeholder for Previous; left empty they use the plugin translations.

A Page progress field renders a progress bar with a Step 2 of 3 caption, announced to screen readers on every page change. It stays visible on every page wherever you place it, and it renders nothing at all on a form with a single page.

Next asks the server to validate the fields of the current page and moves on only once they pass, whether or not the form has live validation turned on; Enter in a field does the same. The submission still validates every field, and if one on an earlier page fails, the form jumps back to that page with the error shown.

Put the break where a page really ends: a break placed after the Submit field leaves a last page with no way to send the form, and two breaks in a row make an empty page.

Note: page breaks are found in the rendered form, so in a custom form template every {{ form_field() }} of a page and the breaks themselves have to sit at the same level. When the breaks do not share one parent element, the form is shown as a single page with the page buttons hidden, and the browser console carries a warning. A component template overriding default.htm has to keep the data-page-validation attribute of the form, or Next moves on without checking the page.

Repeater

A group of fields the visitor can add several times, such as the attendees of an event or several addresses. Save the repeater field first, then open it again: its Repeater tab lists the fields of each row, added and reordered like the fields of the form. Minimum rows makes the visitor fill in that many rows, Maximum rows caps them at up to 50; the form starts with as many rows as the minimum, so an optional repeater shows only its Add another button. Set the field's Placeholder to change the text of that button.

Every row posts its fields as attendees[0][name], attendees[1][name] and so on, and the validation rules of a row field apply to each row on its own, with the error shown next to the input of that row. A row whose fields are all left empty is ignored.

The mail and the submission log list every row. {{ attendees }} holds one line per row, Name: Ann; E-mail: ann@example.com, and {{ attendees_raw }} the rows themselves, for a custom mail template laying them out its own way:

{% for attendee in attendees_raw %}
    {{ loop.index }}. {{ attendee.name }} ({{ attendee.email }})
{% endfor %}

A repeater cannot hold another repeater, nor a field needing a file, a server value or a request of its own: File upload, Signature, Geolocation, Logged in user, reCaptcha, Turnstile, Submit, Page break, Page progress and State select. The fields of a row cannot have conditions, neither they nor the repeater can drive the conditions of other fields, and rows are checked when the form is submitted or a page left, not by live validation.

reCaptcha

Renders Google reCAPTCHA, either v2 (checkbox) or v3 (invisible and score-based, no user interaction).

Create the keys on the reCAPTCHA site — v2 and v3 keys are not interchangeable — and enter them under Settings → Form Builder, tab reCaptcha:

  • Version — reCAPTCHA v2 (Checkbox) or reCAPTCHA v3 (Invisible).
  • Site Key and Secret Key — must match the selected version.
  • Score Threshold (v3 only) — minimum score from 0.0 (likely bot) to 1.0 (likely human) needed to pass. Default is 0.5.
  • Language — language of the widget.
  • Theme — light or dark v2 checkbox widget.

A fresh install is filled with Google's v2 test keys, which always pass and show a testing notice in the widget. Replace them before going live.

Important note: This field must have g-recaptcha-response as field name, and two rows in its validation section — required and recaptcha — to work properly. One rule per row; a rule written as required|recaptcha is rejected.

Turnstile

Renders a Cloudflare Turnstile widget — a captcha that sets no cookies, needs no Google account and is free at any volume. Use it instead of reCaptcha, not next to it.

Create a widget in the Cloudflare dashboard and enter the keys under Settings → Form Builder, tab Turnstile:

  • Site Key and Secret Key — from the widget you created.
  • Theme — auto follows the visitor's colour scheme, or force light / dark.
  • Widget size — normal, flexible (fills the width of its container) or compact.

A fresh install is filled with Cloudflare's test keys, which always pass and show a testing notice in the widget. Replace them before going live.

Important note: The field name is up to you, but the field needs two rows in its validation section — required and turnstile. Without turnstile the token is never verified, and without required an empty token passes.

File upload

Renders a file input.

Filter files selected by a user

To limit the file picker, add an accept custom attribute, for example accept=".pdf,.doc" for PDF and Word files or accept="image/*" for images.

Validation

Add the rules in the field's validation section:

  • required — a file must be chosen,
  • max:512 — at most 512 KB,
  • mimes:pdf — PDF files only,
  • image — images only.

See the available validation rules for more.

Multiple files

To accept more than one file, check Allow multiple files in the Upload Options tab. Then check Nested array based form input next to each rule so it applies to every uploaded file, except the required rule.

Send uploaded files as mail attachments

Uploaded files are attached to the mail by default. Uncheck the option to send the mail without them.

Display mode

Tells the backend how to show the uploaded files in a form submission. Choose image when only images are allowed.

Country select

Renders a dropdown with country options.

Important note: You must install Location Plugin to use this field.

State select

Renders a dropdown with state options. This field depends on country select.

Important note: You must install Location Plugin to use this field.

Translations

Forms, fields and field types are translated with the model translations built into October CMS, one language per site, so no extra plugin is needed. Add a site for each language under Settings → Sites.

There are two ways to fill in a translation in the backend:

  • switch the site with the site selector in the backend and edit the record as usual — every translated attribute is saved for the language of that site,
  • click the globe icon next to a translated field to edit its value for another site in a popup.

Recipients, options and validation messages are repeaters, which the popup cannot edit, so translate them with the site selector. Each site keeps its own copy of the whole list, so after changing an option key or a validation rule on the default site, change it on the translated sites too.

Record Translated attributes
Form name, description, from name, from e-mail, recipients including CC and BCC, success and error message, redirect URL
Field label, default value, placeholder, comment, options, validation messages
Field type name, description

An attribute left empty in a language falls back to the value of the default site, so a form translated only partially never renders blank labels or messages. Duplicating a form copies the translations of the form and of all its fields.

The Translations column of a form's field list shows a flag for each site with its own label; hover it for the text. It is hidden when there is only one site.

Using form data in mail templates

Every submitted field is available in the mail template under its name. For a field named name:

{{ name }}

The value is already processed by Form Builder: dropdowns and radio lists return the label of the selected option, checkbox lists the selected labels separated by commas, a checkbox Yes or No, and country and state selects the name. The value exactly as the browser sent it is available with the _raw suffix:

{{ name_raw }}

Form Submissions

Every submission is stored under Form Builder → Form submissions with the submitted values, the uploaded files, the sender IP address and a preview of the sent e-mail. The autoresponder is stored as a separate submission, marked with the Autoresponder column and filter. Turn logging off per form in the Options tab; a form without a mail template always logs, because the submission would otherwise be lost.

Submissions are pruned by a daily scheduled job after Prune period in days from Settings → Form Builder. It only runs if October's scheduler is running (php artisan schedule:run every minute). Leave the period empty to keep submissions forever.

The list can be filtered by form, autoresponder, send date and IP address.

Submissions can be exported to CSV or JSON from the toolbar. The export follows the filter panel, so filter first to export a subset. The search term and the row checkboxes are not applied to it.

Settings

Plugin settings are available at Settings → Form Builder.

  • reCAPTCHA version, Site key, Secret key, Score threshold, Language, Theme — see the reCaptcha field type above. The pre-filled demo keys work with v2 only.
  • Turnstile Site key, Secret key, Theme, Widget size — see the Turnstile field type above.
  • Prune period in days — how long submissions are kept. Default: 30.

Permissions

Permission Grants
Manage Forms the Forms list; create, update, delete and import/export have their own permission each
Manage field types the Field types list; create, update, delete and import/export have their own permission each. Update also covers restoring the default markup
Manage form submissions the Form submissions list; preview, delete, truncate and export have their own permission each
Manage Settings the plugin settings page

Every backend action checks its permission on the server, so a user without it gets a 403 even when the button is reached by hand.

Events

Event Fired when Payload
formBuilder.overrideForm before the form markup is rendered &$form — replace or change the model
formBuilder.overrideField before each field is rendered &$field, $form
formBuilder.formSubmitted the submission passed validation &$form
formBuilder.extendFormData before the mail and webhook data is built; return the array to replace it $data
formBuilder.beforeSendMessage before the mail is sent; return false to skip the mail, the autoresponder, the submission log and the webhooks $form, $data
formBuilder.beforeSendWebhook before each webhook is called; return false to cancel it $form, $webhook, $payload

Listen in your plugin's boot() method:

Event::listen('formBuilder.overrideForm', function ($form) {
    $form->css_class = 'form-horizontal';
});

Event::listen('formBuilder.overrideField', function ($field, $form) {
    if ($field->name === 'currency') {
        $field->default = 'USD';
    }
});

Event::listen('formBuilder.formSubmitted', function ($form) {
    Log::info("Form {$form->code} submitted", $form->getDataArray());
});

Event::listen('formBuilder.extendFormData', function ($data) {
    $data['foo'] = 'bar';

    return $data;
});

Event::listen('formBuilder.beforeSendMessage', function ($form, $data) {
    $form->from_email = 'john.doe@example.com';
    $form->from_name = 'John Doe';
});

Event::listen('formBuilder.beforeSendWebhook', function ($form, $webhook, $payload) {
    return $payload['data']['email'] !== 'spam@example.com';
});
  • Found the plugin useful on 17 Apr, 2024

    great plugin and support. recommend

  • author

    Replied on 11 Sep, 2026

    Thank you, Petr, for the kind words and the recommendation!

  • Found the plugin useful on 18 May, 2022

    I tested the contact form and clicked submit, I can see the form submitted in Form Logs with all fields filled but unable to receive the contact form via email. Is there a guide for newbie like me to properly setup the contact form configuration?

  • author

    Replied on 11 Sep, 2026

    Hi William, thanks for the review, and sorry for the very late reply. I'm answering here mostly for anyone who runs into the same problem.

    If a submission appears in the log but no e-mail arrives, the form works and the problem is e-mail delivery:

    1. In the form's Recipients tab, replace the demo address admin@domain.tld with your own.
    2. On the Details tab, set Sender email to an address on your domain, or leave it empty to use the mail settings default.
    3. Configure Settings → Mail Configuration and send a test from Settings → Mail Templates. Errors are listed in Settings → Event Log.

    If it still doesn't work, please open an issue at GitHub.

  • Found the plugin useful on 28 Apr, 2022

    Hi, How can override Raw markup Code From latest plugin. In plugin updates said,

    You can override the partial by creating a file in our theme called partials/renderform/fields.htm. and pasting below markup.

    How can update for each form contact-form, subscribe-form, like that

  • author

    Replied on 11 Sep, 2026

    Hi Jess, thanks for the review, and sorry for the very late reply. I'm answering mostly for anyone with the same question.

    The partials/renderform/fields.htm override is gone in current versions. Each form now has its own Custom Template tab. Leave it empty to use the generated markup, or write your own layout and render each field by its name:

    <div class="row">
        <div class="col-6">{{ form_field('first_name') }}</div>
        <div class="col-6">{{ form_field('last_name') }}</div>
    </div>

    So contact-form and subscribe-form can each have a different layout. To change the HTML of a field type for every form, edit it under Form Builder → Field types. It's best to duplicate a type first and edit the copy.

    If you need more help, please open an issue at GitHub.

  • Found the plugin useful on 27 Nov, 2021

    Thanks for the update to support OctoberCMS V2! I have one more problem with the error below. Can you help with this?

    Uncaught ReferenceError: resetForm is not defined

  • author

    Replied on 27 Nov, 2021

    Hi Martijn, thanks for the review!

    resetForm lives in the plugin's form.js, which the component adds to the page through {% scripts %}. This error means the layout doesn't output it. Make sure the layout contains:

    {% framework extras %}
    {% scripts %}

    More details in this issue.

  • Found the plugin useful on 31 Mar, 2021

    So far had no problem.

  • author

    Replied on 11 Sep, 2026

    Thank you, Danny, glad to hear it works well for you!

  • Found the plugin not useful on 28 Jan, 2021

    Support for this plugin is non-existent. They never reply to the forum - I've had simple, open tickets for months. Don't waste your money. For the "#1" paid plugin of all time, this is a complete joke.

  • author

    Replied on 21 Nov, 2021

    Hi Julian, you're right, and I'm sorry. Support back then was far too slow.

    This has changed since. Every report now goes through GitHub Issues, where I answer and track it. The plugin is actively maintained for October CMS 4. The latest release, 5.2.0, adds security fixes, new languages and reworked documentation.

    If you ever give it another try, I'd be glad to help.

  • Found the plugin useful on 13 Jan, 2021

    Just starting my first project with this plugin but I like it so far

  • author

    Replied on 11 Sep, 2026

    Thank you, Remko! Hope the project went well. If anything comes up, you'll find help on GitHub Issues.

  • Found the plugin useful on 12 Jan, 2021

    Great plugin! Thank you for your help. Is any chance to add option for duplicate created already form??

    Best

  • author

    Replied on 11 Sep, 2026

    Thank you, Jacek! Duplicating a form is available: use the copy button in the Actions column of the forms list. Since version 5.2.0 the copy also keeps the RainLab Translate translations.

  • Found the plugin not useful on 14 Sep, 2020

    There is an error when installing.

  • author

    Replied on 16 Sep, 2020

    Hi Morten, sorry for the trouble. The installation error was caused by a change in the October version released at that time and was fixed in version 1.5.0. Current versions install cleanly on October CMS 4.

    If you run into any problem, please report it on GitHub Issues and I'll help you there.

  • Found the plugin not useful on 11 Aug, 2020

    Absolutely not Working, the Error while installing can only be fixed with a plugin:refresh. This Might work for out development environnement, but how would you ever get this to work in Production? Absolutely ridiculous.

  • author

    Replied on 16 Sep, 2020

    Hi Auris, you're right, plugin:refresh is no fix for a production site, and I'm sorry for the trouble. The installation error was caused by a change in the October version released at that time and was fixed in version 1.5.0, so no refresh is needed. Current versions install and update cleanly on October CMS 4 with php artisan october:migrate.

    If you run into any problem, please report it on GitHub Issues and I'll help you there.

  • Found the plugin useful on 15 May, 2020

    No updates for 2 years? Why? We need to add 3 and more recipients in forms. Maybe you can add repeater field in recipients?

  • author

    Replied on 11 Sep, 2026

    Hi Igor, thanks for the suggestion! It's done: the Recipients tab now has repeaters for To, CC and BCC with no limit on the number of addresses, and since version 5.2.0 the submission log stores recipient lists of any length. The plugin is actively maintained again, now for October CMS 4.

  • Found the plugin not useful on 21 Jun, 2019

    Custom support is non-existent, very disappointed.

  • author

    Replied on 11 Sep, 2026

    Sorry for the disappointing experience back then. Support has changed since: every report now goes through GitHub Issues, where I answer and track it, and the plugin is actively maintained for October CMS 4. If you ever give it another try, I'd be glad to help.

  • Found the plugin useful on 23 May, 2019

    За 5 баксов плагин норм

  • author

    Replied on 11 Sep, 2026

    Спасибо за отзыв! Кстати, начиная с версии 5.2.0 плагин полностью переведён на русский язык.

  • Found the plugin useful on 30 Mar, 2019

    Great plugin and easy to use. I'm missing a simple way to store form data in a database though. It can be done width events but requires coding.

  • author

    Replied on 11 Sep, 2026

    Thank you, Ronny! This is built in now: every submission is stored in the database under Form Builder → Form submissions, with the submitted values, uploaded files, sender IP and a preview of the sent e-mail. Submissions can be filtered and exported to CSV or JSON without any coding.

  • Found the plugin not useful on 13 Dec, 2018

    This pluging resets the page every time the persons hits SUBMIT. I do not recommend it

  • author

    Replied on 14 Dec, 2018

    Hi Luis, sorry for the trouble. The form is submitted with AJAX, so the page is not reloaded: the success message appears in place of the form, and a redirect happens only when you set one in the form options. If the page does reload, the layout is missing the AJAX framework. Make sure it contains:

    {% framework extras %}
    {% scripts %}

    If you need help, please open an issue on GitHub Issues.

  • Found the plugin useful on 1 Sep, 2018

    Brilliant and impressive plugin!

    Intuitive to setup and easy to customise (once you discover the html code in Field Types).

    One question - would it be possible to make calculating fields as a field type?

  • author

    Replied on 11 Sep, 2026

    Thank you, Allan! Calculating fields aren't built in yet. For now you can create a custom field type under Form Builder → Field types with a small script in its markup that computes the value from other inputs, for example into a read-only or hidden field, which then gets stored with the submission. If you'd like it as a built-in field type, please add it as a feature request on GitHub Issues.

  • Found the plugin not useful on 22 Apr, 2018

    after installation I have this error

    No hint path defined for [martin.forms]. C:\laragon\www\btp\vendor\laravel\framework\src\Illuminate\View\FileViewFinder.php line 112

    What is the problem ?

  • author

    Replied on 24 Apr, 2018

    Hi Patrick, sorry for the short reply back then. The error doesn't come from Form Builder: martin.forms is the namespace of another plugin, Magic Forms. It usually means a page, partial or mail template still references that plugin after it was removed or disabled. Remove the reference and clear the cache with php artisan cache:clear.

    If Form Builder gives you any trouble, please report it on GitHub Issues.

  • Found the plugin useful on 13 Mar, 2018

    Great work question? can you do model binding to a form

  • author

    Replied on 11 Sep, 2026

    Thank you, Richard! There's no built-in model binding, but events cover both directions. Fill fields from any model before rendering, and save the submission to your own model after validation:

    Event::listen('formBuilder.overrideField', function ($field, $form) {
        if ($field->name === 'email' && $user = Auth::getUser()) {
            $field->default = $user->email;
        }
    });
    
    Event::listen('formBuilder.formSubmitted', function ($form) {
        Lead::create(post());
    });

    See the Events section of the documentation for details.

  • Found the plugin useful on 5 Feb, 2018

    This is a great plug-in, works out of the box. I had some issues with bilingual forms (which originated from the Translate plug-in), which were fixed. Come to think of it, Renatio added a fix although the issue wasn't on this plug-in !

    Another great surprise was a snippet which enables you (your clients) to insert any form created with this plug in into a Static Page with ease.

    • Lacking feature: Duplicate form.

    All in all - great work ! Well worth it ! Thanks a lot Renatio !

  • author

    Replied on 11 Sep, 2026

    Thank you, Ran, for the kind words! Duplicating a form is available now: use the copy button in the Actions column of the forms list. Since version 5.2.0 the copy also keeps the RainLab Translate translations.

  • Found the plugin useful on 14 Jan, 2018

    Can i add flags to country select?

  • author

    Replied on 11 Sep, 2026

    Hi Madars, thanks for the question! Not out of the box: the Country select field uses RainLab Location's form_select_country(), which renders a native <select>, and native selects can't show images. You can create a custom field type under Form Builder → Field types that wraps the select with a JavaScript select library supporting option templates (for example Tom Select) and adds the flags there. If you'd like it built in, please add a feature request on GitHub Issues.

  • Found the plugin useful on 11 Aug, 2017

    Everything is fine but you can not add country and state. If you could provide any documentation for the same will be best.

  • author

    Replied on 11 Sep, 2026

    Hi Dinesh, thanks for the review! Both are available as field types:

    1. Install the RainLab Location plugin.
    2. Add a Country select field and a State select field to your form.

    The state list refreshes automatically when a country is chosen, and the mail and the submission log show the country and state names. Both field types are described in the plugin documentation.

  • Found the plugin not useful on 29 Jul, 2017

    please, update formbuilder it's have some problem

  • author

    Replied on 30 Jul, 2017

    Sorry for the unhelpful reply back then. The plugin has been updated many times since and is actively maintained for October CMS 4. If you still run into a problem, please describe it on GitHub Issues and I'll help you there.

  • Found the plugin useful on 1 Jul, 2017

    I lost a full day trying to build a form with the Ajax framework that validates and accepts file uploads.

    Then I found this plugin, copied the default form and the task was complete in 15 minutes.

    Excellent extension!

  • author

    Replied on 11 Sep, 2026

    Thank you, Paddy! Glad it saved you the day. That's exactly what the plugin is for.

  • Found the plugin useful on 9 Jun, 2017

    Dearest Author of the plugin

    thank you for your work for all of us. Im searching a not to difficult possibility (Im on a low programmer level) to create a form that saves data into a corresponfing table, were row can be edited. 0) Where is the support area to ask you in the correct way? 1) Is that possible? 2) Would you create a plugin with the form builder and then connect the form with the table somehow? But how? I do not see a field for the action of the form itself.

    Thanx a lot

    Kai

  • author

    Replied on 11 Sep, 2026

    Hi Kai, thank you, and sorry for the very late reply.

    1. Please ask on GitHub Issues.
    2. Yes. Every submission is already stored in the database under Form Builder → Form submissions, where you can view, filter and export it, but not edit it.
    3. For editable rows, create a Tailor blueprint (October CMS 3 and 4) for your table. You get the backend list and edit form without writing a plugin. Then copy each submission into it with one event listener:
    Event::listen('formBuilder.formSubmitted', function ($form) {
        if ($form->code === 'my-form') {
            $entry = \Tailor\Models\EntryRecord::inSection('Leads');
            $entry->fill(post());
            $entry->save();
        }
    });

    The form has no action field because it's submitted with AJAX to the component. Events are the way to hook into it.

  • Found the plugin useful on 8 Jan, 2017

    Useful plugin but I have some issues:

    1. Plugin needs css bootstrap to display "actions" but doesn't mention this in doc's.
    2. Captcha does not display label so I had to inject a ::before css
    3. Need more info in the doc's about mail templates and mail services etc?! Would be nice if there was a video demo of the plugin.

    Useful plugin will buy again, but please update your doc's info a bit more...

  • author

    Replied on 11 Sep, 2026

    Hi Sally, thank you for the detailed feedback, and sorry for the very late reply. Most of it is addressed now:

    • The reCAPTCHA field renders its label.
    • The documentation covers using form data in mail templates, and the mail itself is sent through October's Settings → Mail Configuration.
    • Instead of a video, there's a live demo; the login details are in the plugin description.

    The default field markup uses Bootstrap 5 classes. With another CSS framework, edit the markup under Form Builder → Field types. Thanks for pointing it out, I'm adding it to the documentation.

  • Found the plugin not useful on 3 Jan, 2017

    For basic use, FormBuilder works great. It's a very powerful plugin, but it lacks in overall stability. Too frequently it throws errors if you have Rainlab.Translate installed which is were this plugin should excel.

    We'd give it 3/5 but still a not useful as we are disappointed every time we try to use it in combination with Translate.

  • author

    Replied on 19 Mar, 2017

    Hi, thanks for the honest review, and sorry for the trouble back then. The errors came from RainLab Translate itself and were worked around in 1.2.9. Today Form Builder works with RainLab Translate and October's multisite: form names, labels, options, messages and validation messages are translatable, and since 5.2.0 duplicating a form keeps its translations. Support for October's native translations is on the roadmap.

    If anything still breaks, please report it on GitHub Issues.

  • Found the plugin useful on 20 Sep, 2016

    Great Plugin and great support! Thank you!

  • author

    Replied on 11 Sep, 2026

    Thank you, Gerald!

  • Found the plugin useful on 9 Sep, 2016

    Great Plugin and really easy to use!!! Thanks to the developer, this plugin makes Forms much easier!

  • author

    Replied on 11 Sep, 2026

    Thank you, Gerald, for the kind words! By the way, the plugin is fully translated into German.

  • Found the plugin useful on 8 Sep, 2016

    Very good product. Great features.

  • author

    Replied on 11 Sep, 2026

    Thank you, glad you like it!

  • Found the plugin useful on 26 Aug, 2016

    Perfect Plugin to handle most complex forms. It covers almost every aspect which is required to build a complex forms. Great work Renato.

  • author

    Replied on 11 Sep, 2026

    Thank you, Vijay, for the kind words!

  • Found the plugin useful on 6 Aug, 2016

    Very nice plugin!

  • author

    Replied on 11 Sep, 2026

    Thank you!

  • Found the plugin useful on 6 Jul, 2016

    Great plugin with a lot of flexibility for custom projects. Also, the support is timely and very helpful. I definitely recommend this plugin for OctoberCMS forms.

  • author

    Replied on 11 Sep, 2026

    Thank you, Tyson, for the kind words and the recommendation!

  • Found the plugin useful on 23 Jun, 2016

    Great plugin! Works as expected. Would recommend allowing users to style labels directly though!

  • author

    Replied on 11 Sep, 2026

    Thank you, Nick! Labels can be styled per field now: set Label CSS classes in the field's HTML & CSS tab. For full control, the label markup of each field type is editable under Form Builder → Field types.

  • Found the plugin useful on 14 Jun, 2016

    Awesome plugin! Very well made. Simple to use and highly costumizable.

    Would recommend it to anyone. Well worth the money!

  • author

    Replied on 11 Sep, 2026

    Thank you, Elian, for the kind words and the recommendation!

  • Found the plugin useful on 7 Jun, 2016

    This is an incredibly useful and very well done plugin. I recommend it to everyone that need to build forms that are easy to build and easy to maintain.

  • author

    Replied on 11 Sep, 2026

    Thank you, Juan, for the kind words and the recommendation!

  • Found the plugin useful on 17 May, 2016

    Very good plugin! Thanks.

  • author

    Replied on 11 Sep, 2026

    Thank you, MyeongCheol!

  • Found the plugin useful on 22 Feb, 2016

    Great plugin, very easy to use and integrate :)

  • author

    Replied on 11 Sep, 2026

    Thank you, glad to hear it!

  • Found the plugin useful on 3 Feb, 2016

    There is awesome plugin and the best support I've ever seen. Thank you very much for your job.

  • author

    Replied on 11 Sep, 2026

    Thank you, Marina, that means a lot! By the way, since version 5.2.0 the plugin is fully translated into Russian.

  • Found the plugin useful on 21 Jan, 2016

    Very good plugin. Powerful and easy to use.

  • author

    Replied on 11 Sep, 2026

    Thank you for the kind words!

  • Found the plugin useful on 17 Jan, 2016

    This is a professionally written plugin that is really useful if you need lots of forms.

  • author

    Replied on 11 Sep, 2026

    Thank you, Andy, glad it serves you well!

  • Found the plugin useful on 16 Dec, 2015

    Excellent plugin, and excellent support from Renatio. I would ALL of Renatio's plugins are a must for any serious OctoberCMS developer.

  • author

    Replied on 11 Sep, 2026

    Thank you so much for the kind words and for recommending my plugins!

  • Found the plugin useful on 7 Oct, 2015

    Simply a SUPERB plugin! The ability to customise each form, right down to the styles, layouts, and classes is just fantastic. The one support question I had was answered remarkably quickly. I've got multiple contact forms assigned to individual partials that the client is able to drop into their pages using the "Snippets" section of the Rain.Lab Pages plugin. Developer and client very happy. Highly recommended!

  • author

    Replied on 11 Sep, 2026

    Thank you, Gavin, for the kind words! A small tip: the form component is now registered as a RainLab Pages snippet itself, so clients can drop any form into a page and choose it there, without a separate partial for each form.

  • Found the plugin not useful on 14 Sep, 2015

    lake of stuff like date, time...input and setting the column..make wizard form!

  • author

    Replied on 15 Sep, 2015

    Hi Daniel, sorry for the reply back then. All three are covered now:

    • Date, Time and Datetime are built-in field types, together with E-mail, Phone, URL, Numeric and Color Picker.
    • Columns: give each field a wrapper class such as col-md-6, or lay the form out freely in the form's Custom Template tab.
    • Wizard (multi-page) forms are on the roadmap.

    If you need help, please ask on GitHub Issues.

6.0.1

Fix links with several query parameters in e-mails, keep the rules and option keys of the default site on translated sites, export webhooks without their secret.

Nov 01, 2026

6.0.0

Translate forms, fields and field types with the translations built into October 4.4 instead of RainLab.Translate.

Nov 01, 2026

5.3.0

Improve form accessibility with linked error messages, marked required fields and fieldset groups.

Nov 01, 2026

5.2.0

Security release. Escape submitted values in the submission preview, sandbox the e-mail preview and check the create, update, delete and truncate permissions in every AJAX handler.

Sep 11, 2026

5.1.6

Rename the FormLogs e-mail preview action to preview_email.

Sep 09, 2026

5.1.5

Add reCAPTCHA v3 support with score-based verification, expose only site_key, version, theme and lang to field markup, fix the 404 on the FormLogs e-mail preview under October 4.3.5 and later, stop the ajax:promise listener throwing on element-less requests, save the autoresponder in its own form log with a list filter.

Sep 09, 2026

5.1.4

Add type hints, refactor code, expand test coverage, replace bkwld/cloner with native duplicate() methods.

Sep 09, 2026

5.1.3

Fix validation and add tests.

Dec 29, 2025

5.1.2

Fix field type validation.

Dec 01, 2025

5.1.1

Fix passing form model to mail template.

Dec 01, 2025

5.1.0

Add raw field values (fieldname_raw) support.

Dec 01, 2025

5.0.5

Refactor to use pluck() function.

Oct 07, 2025

5.0.4

Parse form markup with Twig. Thanks @apinard

Aug 29, 2025

5.0.3

Update dependencies.

Jul 12, 2025

5.0.2

Add compatibility.

Jul 07, 2025

5.0.1

Require October 4.

Jun 30, 2025

4.0.8

Fix minor issues with form.js. Fix using external property values for formCode property.

May 02, 2025

4.0.7

Fix removing form log when using attachOne relation file upload field.

Oct 01, 2024

4.0.6

Allow to completely override form in plugin events. Thanks @m49n

May 11, 2024

4.0.5

Add hidden field type. Add events to override form and fields before rendering form markup.

Mar 05, 2024

4.0.4

Allow to select forms and field types for export.

Feb 22, 2024

4.0.3

Fix scroll after form submission.

Nov 11, 2023

4.0.2

Add setting to turn off sending uploaded files as mail attachment.

Oct 08, 2023

4.0.1

Minor fix.

Sep 21, 2023

4.0.0

Remove responsiv/uploader-plugin support with native October ajax file upload.

Sep 21, 2023

3.1.3

Add support for October snippets.

Sep 07, 2023

3.1.2

Allow to disable form logs.

Jun 01, 2023

3.1.1

Fix permissions.

Nov 23, 2022

3.1.0

Major rework of the plugin. See upgrade guide for list of changes.

Nov 23, 2022

3.0.0

Require October CMS 3.0.

Nov 23, 2022

2.2.0

Rewrite querying mail templates.

May 17, 2022

2.1.7

Fix for October 3.x.

Apr 24, 2022

2.1.6

Fix raw fields markup for PHP < 7.4.

Dec 02, 2021

2.1.5

Minor fix.

Nov 28, 2021

2.1.4

Minor fix.

Nov 28, 2021

2.1.3

Raw fields markup.

Nov 27, 2021

2.1.2

Improve reset field type to default.

Nov 25, 2021

2.1.1

Minor fixes.

Nov 25, 2021

2.1.0

Add patch 2.0 console command for easy upgrade process.

Nov 20, 2021

2.0.1

Add support for October v2.0. Drop support for October v1.0.

Nov 20, 2021

1.5.0

Elevate plugin permissions.

Sep 16, 2020

1.4.9

Fix issue with field options.

Jul 23, 2018

1.4.8

Fix issue with ReCaptchaServiceProvider class.

Jul 21, 2018

1.4.7

Fix multilingual fields.

Jul 18, 2018

1.4.6

Generate form code automatically.

Jul 18, 2018

1.4.5

Use October Default Mail Layout for example Templates.

Jul 18, 2018

1.4.4

Improve RainLab.Location plugin integration.

Jul 18, 2018

1.4.3

Dynamic form reply to fields.

Jul 13, 2018

1.4.2

Fix fields and sections translation.

Jan 31, 2018

1.4.1

Set default reCaptcha keys for testing.

Jan 31, 2018

1.4.0

!!! Nicer form field validation.

Oct 18, 2017

1.3.1

Fix example forms seeding.

Apr 22, 2017

1.3.0

Allow to use CMS filters and functions in field templates.

Apr 22, 2017

1.2.9

Fix RainLab.Translate compatibility issues.

Mar 19, 2017

1.2.8

Fix sending email with file attachment for October build 401+

Mar 12, 2017

1.2.7

Improve seeding mail templates. Add Contact Form and Default Form. Update Mail Layout.

Mar 12, 2017

1.2.6

Export form logs to CSV file.

Feb 08, 2017

1.2.5

Allow to duplicate a form.

Sep 19, 2016

1.2.4

Minor changes.

May 14, 2016

1.2.3

German translation.

Feb 10, 2016

1.2.2

Allow to manually specify url for redirect.

Feb 03, 2016

1.2.1

Allow for custom validation messages.

Feb 01, 2016

1.2.0

Dutch translation.

Jan 29, 2016

1.1.9

Add comment to fields.

Jan 22, 2016

1.1.8

Add HTML preview in logs.

Jan 08, 2016

1.1.7

Add sections feature.

Jan 08, 2016

1.1.6

Add reply to and autoresponse functionality.

Dec 08, 2015

1.1.5

Add Event to extend default functionality.

Nov 09, 2015

1.1.4

RainLab Location Plugin support.

Nov 09, 2015

1.1.3

Minor changes.

Oct 19, 2015

1.1.2

Allow for multiple forms on the same cms page. Fix required validation rule for fileuploader field type.

Oct 19, 2015

1.1.1

Use Twig::parse() facade. Only update for October build 300 and above.

Oct 05, 2015

1.1.0

!!! Important update

Oct 05, 2015

1.0.4

Add simple logs.

Sep 14, 2015

1.0.3

Add file attachment field type.

Sep 14, 2015

1.0.2

Reference __SELF__ in component partial.

Sep 06, 2015

1.0.1

First version of Form Builder plugin.

Aug 24, 2015

Upgrade guide

Versions not listed here need no action. Back up the database before upgrading.

Upgrading To 2.0.1

Requires October CMS 2.x and PHP 7.3. Upgrading from 1.5.0 needs a reinstall or php artisan formbuilder:patch 2.0.

Upgrading To 3.0.0

Requires October CMS 3.0 and PHP 8.0.

Upgrading To 3.1.0

  • Field types are rewritten for Bootstrap 5; forms rendered with an older framework need their markup adjusted.
  • Permissions are now granular, so review the roles after the upgrade.
  • Validation uses the AJAX Framework extras ({% framework extras %} in the layout).

Upgrading To 4.0.0

Upgrade to 3.1.3 first and back up the database.

  • The responsiv/uploader-plugin integration is replaced by native AJAX file uploads: the migration adds the new upload field type and moves the old upload fields to it. Check the forms with uploads afterwards.

Upgrading To 5.0.1

Requires October CMS 4.x.

Upgrading To 5.1.0

Field IDs are now unique per form. Restore the field types to the default markup to pick this up; customised field types need the field_id variable added by hand.

Upgrading To 5.1.4

Forms and field types are duplicated with native duplicate() methods instead of bkwld/cloner, so the cloner::cloning and cloner::cloned events are no longer fired.

Upgrading To 5.1.5

Run php artisan october:migrate.

  • Field type markup receives only settings.site_key, settings.version, settings.theme and settings.lang; customised reCAPTCHA markup must be restored to default or updated by hand to support v3.
  • The autoresponder is saved as its own form submission, so a form with both switches on produces two entries per submission.

Upgrading To 5.2.0

Security release. Upgrade every installation running 5.1.x. Requires PHP 8.2. Run php artisan october:migrate.

  • Submitted values are now escaped in the submission preview, and every backend AJAX handler checks its permission on the server.
  • Users who duplicate forms or field types, toggle field visibility or restore the default markup now need the matching Create or Update permission; Clear form submissions needs Truncate form submissions. Review the roles under Settings → Administrators → Roles.
  • Field names must be unique within the form and use only letters, digits, dashes and underscores; rename an older field that breaks this rule (and its variable in the mail template) when saving it fails.
  • Field HTML is inserted after the form template is parsed, so Twig syntax typed into a label or a default value is rendered literally.
  • Merge the changes into form.js if you ship a customised copy: validation errors now clear as the visitor corrects the field, and a second submit is blocked while the first is pending.

Upgrading To 5.3.0

Run php artisan october:migrate.

  • Field types still on the default markup are refreshed automatically; restore customised ones under Form Builder → Field types or add the error and help ids, aria-* attributes and the new required variable by hand.
  • Required fields now show an asterisk, checkbox and radio lists render as a fieldset with a legend and option ids {field_id}-option-{key}, and the Section heading is an h2 styled as h4, so check theme CSS and JS that target these elements.
  • Merge the form.js changes if you ship a customised copy.

Upgrading To 6.0.0

Requires October CMS 4.4. Run php artisan october:migrate.

  • The migration installs the new field types and adds length limits to unchanged fields of the seeded forms.
  • It also copies the RainLab.Translate translations of forms, fields and field types into October's built-in translations, leaving the old rows untouched. Do not run php artisan translate:import-attributes without --model afterwards, as it overwrites those translations.
  • Merge the form.js changes if you ship a customised copy.
  • A customised default mail template prints a repeater as one line per row.
  • A geolocation value reaches mail templates and formBuilder.* listeners as a Twig\Markup object; cast it with (string) before comparing.

Upgrading To 6.0.1

Validation rules and option keys of a field are shared by all sites; a translated site translates only the validation messages and option labels. A field that had different rules on a translated site now uses the rules of the default site.