PHPackages                             typo3/formbuilder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. typo3/formbuilder

Abandoned → [neos/formbuilder](/?search=neos%2Fformbuilder)Neos-package[Utility &amp; Helpers](/categories/utility)

typo3/formbuilder
=================

Flow Form Framework integration into Neos CMS

3.0.4(2mo ago)195.1k33[5 issues](https://github.com/neos/form-builder/issues)[6 PRs](https://github.com/neos/form-builder/pulls)GPL-3.0+PHPCI failing

Since Aug 29Pushed 2mo ago3 watchersCompare

[ Source](https://github.com/neos/form-builder)[ Packagist](https://packagist.org/packages/typo3/formbuilder)[ Fund](https://shop.neos.io/neosfunding/)[ RSS](/packages/typo3-formbuilder/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (39)Used By (0)

Flow Form Framework integration into Neos CMS
=============================================

[](#flow-form-framework-integration-into-neos-cms)

This package adds a builder for the [Flow Form Framework](https://github.com/neos/form)to the [Neos CMS](https://neos.io) backend. It also comes with [Fusion](https://neos.readthedocs.io/en/stable/CreatingASite/Fusion/index.html)prototypes that allow for dynamic Fusion based Form definitions.

Related Packages
----------------

[](#related-packages)

Make sure to have a look at the other Flow Form Framework [Related Packages](https://github.com/neos/form/#related-packages)

Usage
-----

[](#usage)

Install this package using [composer](https://getcomposer.org/):

```
composer require neos/form-builder

```

> **Note:** This package requires the `neos/neos` package in version 3.1 or higher

In the Neos backend there's now a new Content Element type that can be used:

[![Create Wizard](Documentation/Images/CreateWizard.png "New "Form" Content Element")](Documentation/Images/CreateWizard.png)

> **Note:** If you have the `Neos.NodeTypes` package installed, there are two types of Forms that can be inserted. The following snippet can be added to the sites `NodeTypes.yaml` in order to disable the Neos.NodeTypes Form:

```
'Neos.NodeTypes:Form': ~
```

Now, *Form Elements* can be added to the Form:

[![Add Form Element](Documentation/Images/AddFormElements.png "Adding Form Elements")](Documentation/Images/AddFormElements.png)

To each Form Element *Validators* can be added and some elements allow to create child Form Elements or *Select Options*. Besides, every form allows to create *Further Form Pages* that can contain elements themselves. And, of course, *Form Finishers* can be added to the Form.

So there are quite a lot of Content Collections and they are easily confused. One solution is to use the *Structure Tree* when working on complex forms:

[![Structure Tree](Documentation/Images/StructureTree.png "Form in the Structure Tree")](Documentation/Images/StructureTree.png)

In addition this package comes with some custom StyleSheet that should make the Form Builder more accessible:

Adjust appearance of the Form Builder
-------------------------------------

[](#adjust-appearance-of-the-form-builder)

This package provides some CSS that can be included in order to adjust the styling of the Form Builder within the Neos Backend. The following Fusion snippet can be added in order to include the custom CSS when in the Neos Backend (as long as the page Fusion prototype extends from `Neos.Neos:Page`):

```
prototype(Neos.Neos:Page) {
    head.formBuilderStyles = Neos.Fusion:Tag {
        tagName = 'link'
        attributes {
            rel = 'stylesheet'
            href = Neos.Fusion:ResourceUri {
                path = 'resource://Neos.Form.Builder/Public/Styles/Backend.css'
            }
        }
        @position = 'end'
        @if.isInBackend = ${documentNode.context.inBackend}
    }
}

```

As a result the form will look something like this in the Backend:

[![Custom Styles](Documentation/Images/CustomStyles.png "Form Builder with custom styles")](Documentation/Images/CustomStyles.png)

Build forms with Fusion
-----------------------

[](#build-forms-with-fusion)

The main purpose of this package is its integration to the Neos Backend, using Content Repository Nodes to represent the definition of a Form. But in some cases it can be very useful to define Forms in pure Fusion:

```
prototype(Some.Package:ContactForm) < prototype(Neos.Form.Builder:Form) {
    presetName = 'default'
    firstPage {
        elements {
            name = Neos.Form.Builder:SingleLineText.Definition {
                label = 'Name'
                validators {
                    stringLength = Neos.Form.Builder:StringLengthValidator.Definition {
                        options.minimum = 5
                    }
                }
                properties.placeholder = 'Your name'
            }
            email = Neos.Form.Builder:SingleLineText.Definition {
                label = 'Email'
                validators {
                    emailAddress = Neos.Form.Builder:EmailAddressValidator.Definition
                }
                properties.placeholder = 'Your email address'
            }
            interests = Neos.Form.Builder:MultipleSelectCheckboxes.Definition {
                label = 'Interests'
                required = ${false}
                properties.options {
                    neos = 'Neos CMS'
                    flow = 'Neos Flow'
                    chicken = 'Chickens'
                }
            }
            comment = Neos.Form.Builder:MultiLineText.Definition {
                label = 'Message'
                properties.placeholder = 'Your Comment'
            }
        }
    }
    finishers {
        confirmationFinisher = Neos.Form.Builder:ConfirmationFinisher.Definition {
            options {
                message = 'Thank you for your comment, {name}!'
            }
        }
    }
}

```

To create multi-page forms the `furtherPages` field can be used:

```
prototype(Some.Package:ContactForm) < prototype(Neos.Form.Builder:Form) {
    // ...
    furtherPages {
        page2 = Neos.Form.Builder:FormPage.Definition {
            elements {
                elementOnPage2 = Neos.Form.Builder:SingleLineText.Definition {
                    label = 'Element on page 2'
                }
            }
        }
        preview = Neos.Form.Builder:PreviewPage.Definition
    }
}

```

Now the `Some.Package:ContactForm` prototype can be used just like any other Content Element (or even as Document).

In this case the result is just a static contact Form, so there is not much difference to YAML-based Form Definitions. But obviously use all the Fusion and Eel power can be used to create dynamic forms. For example Form fields could be pre-filled with the authenticated user's data:

```
// ...
    someFormField = Neos.Form.Builder:SingleLineText.Definition {
        defaultValue = ${Security.account.accountIdentifier}
        // ...

```

In order to set options based on the current Fusion context, the values have to be added to the Forms context explicitly in order to make them available in the elements/finisher configuration:

```
prototype(Some.ContactForm:Contact) < prototype(Neos.Form.Builder:Form) {

    // Redirect to the first child node of type "Some.Target:NodeType" upon form submission
    @context.redirectUri = Neos.Neos:NodeUri {
        node = ${q(documentNode).children('[instanceof Some.Target:NodeType]').get(0)}
    }

    // ...

    finishers {
        redirectFinisher = Neos.Form.Builder:RedirectFinisher.Definition {
            options {
                uri = ${redirectUri}
            }
        }
    }
}

```

Caching
-------

[](#caching)

By default, all `Neos.Form.Builder:Form` implementations are *not cached*. This is done in order to avoid nasty bugs when assumed otherwise.

To optimize performance, this behavior can be changed for individual forms to make them (partially) cached. I.e. the static form above could be changed as follows:

```
prototype(Some.Package:ContactForm) < prototype(Neos.Form.Builder:Form) {
    @cache {
        mode = 'dynamic'
        entryIdentifier {
            node = ${node}
        }
        entryTags {
            1 = ${Neos.Caching.nodeTag(node)}
        }
        entryDiscriminator = ${request.httpRequest.methodSafe ? 'static' : false}
        context {
            1 = 'node'
            2 = 'documentNode'
        }
    }
    // ...

```

With that in place, the initial Form rendering is cached and the mode is changed to "uncached" when the Form is submitted (= unsafe request).

> **Note:** The `dynamic` Cache mode only works reliably with Neos versions 2.3.15+ and 3.1.5+

Custom Form Elements
--------------------

[](#custom-form-elements)

The Form Elements defined in the `default` preset (and available in this package) are meant as a quickstart to simple Forms. The main strength of the Flow Form Framework comes with it's easy creation of custom Form Elements, Validators and Finishers (see [documentation](https://flow-form-framework.readthedocs.io/en/latest/adjusting-form-output.html#creating-a-new-form-element)).

To allow custom Form Elements to be used in the Form Builder, a corresponding `NodeType` has to be defined:

```
'Some.Package:SomeFormElementNodeType':
  superTypes:
    'Neos.Form.Builder:FormElement': TRUE
  ui:
    label: 'Some label'
    # add the new item in the "Custom Form Elements" section. Other options are form.elements, form.select and form.container
    group: 'form.custom'
```

### Form Element Mapping

[](#form-element-mapping)

For the Form Element nodes, a corresponding Fusion Prototype named `.Definition`is assumed to define the Form Element. (The `.Definition` suffix is used in order to prevent naming conflicts with prototypes that *render* the Form Element).

The corresponding Fusion Prototype for the Node Type specified above could look something like this:

```
prototype(Some.Package:SomeFormElementNodeType.Definition) < prototype(Neos.Form.Builder:FormElement.Definition) {
    formElementType = 'Some.Package:SomeFormElement'
}

```

Alternatively the mapping to a Form Element Type can be specified via the `options.form.formElementType`setting in the Node Type configuration if no custom Fusion Prototype is required:

```
'Some.Package:SomeFormElementNodeType':
  // ...

  options:
    form:
      formElementType: 'Some.Package:SomeFormElement'
```

If that option is set, the regular `Neos.Form.Builder:FormElement.Definition` Fusion Prototype is used to evaluate the definition of that Form Element.

In any case that Form Element must be existent in the configured Form Preset in order to be rendered correctly.

### Example: Custom "title" selector

[](#example-custom-title-selector)

A `title` selector is a common requirement for contact forms. Instead of adding a generic select element and having to add the options manually for every instance, we can easily create a custom element for that.

First, a new NodeType is required:

`NodeTypes.yaml`:

```
'Some.Package:Title':
  superTypes:
    'Neos.Form.Builder:FormElement': TRUE
  ui:
    label: 'Title'
    group: 'form.custom'
```

The corresponding Fusion maps the Form Element and specifies the selectable options:

`Title.fusion`:

```
prototype(Some.Package:Title.Definition) < prototype(Neos.Form.Builder:FormElement.Definition) {
    # we map this to the existing SingleSelectDropdown Form Element
    formElementType = 'Neos.Form:SingleSelectDropdown'
    properties {
        options = Neos.Form.Builder:SelectOptionCollection {
            mrs = 'Mrs.'
            mr = 'Mr.'
            miss = 'Miss'
            ms = 'Ms.'
            dr = 'Dr.'
            prof = 'Prof.'
        }
    }
}

```

> **Note:** In this case we map the new Element to the `SingleSelectDropdown`Form Element from the Neos.Form package. We could use `SingleSelectRadioButtons` instead, or to a custom element. Or have a dynamic mapping like in the following example

### Example: Custom selector with dynamic Form Element type mapping

[](#example-custom-selector-with-dynamic-form-element-type-mapping)

In this example we create a selector for Newsletter categories. It's pretty similar to the previous example. But in this case we want to give the editor a bit more control and allow them to specify whether *multiple* categories can be selected. So we create the NodeType with a property `multiple`:

`NodeTypes.yaml`:

```
'Some.Package:NewsletterCategories':
  superTypes:
    'Neos.Form.Builder:FormElement': TRUE
    'Neos.Form.Builder:DefaultValueMixin': FALSE
  ui:
    label: 'Newsletter Category Selector'
    group: 'form.select'
  properties:
    'multiple':
      type: boolean
      ui:
        label: 'Allow multiple'
        inspector:
          group: 'formElement'
```

..and map the Form Element depending on that property in the Fusion prototype:

`NewsletterCategories.fusion`:

```
prototype(Some.Package:NewsletterCategories.Definition) < prototype(Neos.Form.Builder:FormElement.Definition) {
    # depending on the "multiple" property this will render checkboxes or radio buttons
    formElementType = ${this.properties.multiple ? 'Neos.Form:MultipleSelectCheckboxes' : 'Neos.Form:SingleSelectRadiobuttons'}
    properties {
        options = Neos.Form.Builder:SelectOptionCollection {
            events = 'Events'
            corporate = 'Corporate'
            marketing = 'Marketing'
        }
    }
}

```

#### Dynamic options

[](#dynamic-options)

Instead of hard-coding the options in the fusion prototype, we can use `FlowQuery` to retrieve them from the Content Repository. The following snippet will for example make any `NewsletterCategory` node selectable:

`NewsletterCategories.fusion`:

```
    // ...
    properties {
        options = Neos.Form.Builder:SelectOptionCollection {
            items = ${q(site).children('[instanceof Some.Package:NewsletterCategory]')}
            itemRenderer = Neos.Fusion:DataStructure {
                value = ${item.aggregateId}
                label = ${q(item).property('title')}
            }
        }
    }

```

Upgrade to version 3
--------------------

[](#upgrade-to-version-3)

### Neos.Form.Builder:SelectOptionCollection

[](#neosformbuilderselectoptioncollection)

The `Neos.Form.Builder:SelectOptionCollection` prototype has been changed and uses now `items` instead of `collection`.

Also, the way how dynamic options got collected has been changed. Instead of defining the property path, you now need to use a renderer to render the `value` and `label` of your option.

###  Health Score

56

—

FairBetter than 98% of packages

Maintenance80

Actively maintained with recent releases

Popularity31

Limited adoption so far

Community27

Small or concentrated contributor base

Maturity75

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~100 days

Recently: every ~77 days

Total

32

Last Release

72d ago

Major Versions

1.2.1 → 2.0.02019-11-13

1.3.0 → 2.1.02020-06-30

2.3.6 → 3.0.02024-12-03

2.3.7 → 3.0.32025-06-25

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/11575267?v=4)[Neos](/maintainers/neos)[@neos](https://github.com/neos)

![](https://avatars.githubusercontent.com/u/95582?v=4)[Robert Lemke](/maintainers/robertlemke)[@robertlemke](https://github.com/robertlemke)

---

Top Contributors

[![bwaidelich](https://avatars.githubusercontent.com/u/307571?v=4)](https://github.com/bwaidelich "bwaidelich (97 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (20 commits)")[![daniellienert](https://avatars.githubusercontent.com/u/642226?v=4)](https://github.com/daniellienert "daniellienert (17 commits)")[![dlubitz](https://avatars.githubusercontent.com/u/13046100?v=4)](https://github.com/dlubitz "dlubitz (16 commits)")[![samsauter](https://avatars.githubusercontent.com/u/8954166?v=4)](https://github.com/samsauter "samsauter (16 commits)")[![mhsdesign](https://avatars.githubusercontent.com/u/85400359?v=4)](https://github.com/mhsdesign "mhsdesign (5 commits)")[![paavo](https://avatars.githubusercontent.com/u/1118783?v=4)](https://github.com/paavo "paavo (4 commits)")[![marcrobertscamao](https://avatars.githubusercontent.com/u/249061?v=4)](https://github.com/marcrobertscamao "marcrobertscamao (4 commits)")[![Sebobo](https://avatars.githubusercontent.com/u/596967?v=4)](https://github.com/Sebobo "Sebobo (3 commits)")[![dfeyer](https://avatars.githubusercontent.com/u/221173?v=4)](https://github.com/dfeyer "dfeyer (2 commits)")[![markusguenther](https://avatars.githubusercontent.com/u/1014126?v=4)](https://github.com/markusguenther "markusguenther (2 commits)")[![gerhard-boden](https://avatars.githubusercontent.com/u/10533739?v=4)](https://github.com/gerhard-boden "gerhard-boden (2 commits)")[![dimaip](https://avatars.githubusercontent.com/u/837032?v=4)](https://github.com/dimaip "dimaip (2 commits)")[![vertexvaar](https://avatars.githubusercontent.com/u/5594393?v=4)](https://github.com/vertexvaar "vertexvaar (1 commits)")[![ahaeslich](https://avatars.githubusercontent.com/u/1756367?v=4)](https://github.com/ahaeslich "ahaeslich (1 commits)")[![dimitriadisg](https://avatars.githubusercontent.com/u/14919500?v=4)](https://github.com/dimitriadisg "dimitriadisg (1 commits)")[![gerdemann](https://avatars.githubusercontent.com/u/690536?v=4)](https://github.com/gerdemann "gerdemann (1 commits)")[![jacrasmussen](https://avatars.githubusercontent.com/u/2988654?v=4)](https://github.com/jacrasmussen "jacrasmussen (1 commits)")[![jobee](https://avatars.githubusercontent.com/u/5636715?v=4)](https://github.com/jobee "jobee (1 commits)")[![kabarakh](https://avatars.githubusercontent.com/u/1228395?v=4)](https://github.com/kabarakh "kabarakh (1 commits)")

---

Tags

formhacktoberfestneoscms

### Embed Badge

![Health badge](/badges/typo3-formbuilder/health.svg)

```
[![Health](https://phpackages.com/badges/typo3-formbuilder/health.svg)](https://phpackages.com/packages/typo3-formbuilder)
```

###  Alternatives

[sitegeist/monocle

An living-styleguide for Neos that is based on the actual fusion-code

45315.9k10](/packages/sitegeist-monocle)[sitegeist/kaleidoscope

Responsive-images for Neos

29352.4k10](/packages/sitegeist-kaleidoscope)[kaufmanndigital/gdpr-cookieconsent

A ready-to-run package, that integrates an advanced cookie consent banner into your Neos CMS site.

2540.7k](/packages/kaufmanndigital-gdpr-cookieconsent)[neos/seo

SEO configuration and tools for Neos

13990.5k24](/packages/neos-seo)[shel/neos-colorpicker

A plugin for Neos CMS which provides a colorpicker editor

1494.4k6](/packages/shel-neos-colorpicker)[neos/form-builder

Flow Form Framework integration into Neos CMS

19347.1k18](/packages/neos-form-builder)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
