RFC - Fusion Form Handling / Formbuilder

As the development of fusion-forms https://github.com/neos/fusion-form slowly comes to an end we should start to think about the next steps after and look at the topics formhandling and editable forms again.

Fusion forms will allow us to implement editable forms really easy as we already are able to handle all fields that are passed to the form as rendered html. The only missing building blocks are data-handling and the validation.

In the following i want to line out my idea how a much simpler form handling solution could work that does not need a special runtime and the complexity of the current form framework. I hope to collect some feedback to get a better understanding of the needed fetures and how-simple / complex a solution needs to be.

I have no plans to work on that in the near future unless a customer project appears. But if anyone is willing to implement this or similar things i will gladly help.

Neos Formhandling

  1. In general forms should be submitted to a controller action that is responsible for validation, issuing a signal or event that other packages can listen to and finally sends a redirect to the tank you page or send the user back when validation errors occurred. No subrequests needed here.

  2. There should be two different ways to define forms via settings and via nodetypes that can be installed independently of each other.

  3. The form controller would perform the following steps.

    1. Fetch validations rules and target-uri for the submitted form (the information about the origin has to be transported safely)
    2. Apply validation and send the request back to the _referrer if validation errors occurred
    3. If the data was validated successfully submit the event/signal “form contact was submitted with data …”
    4. Send redirect to the thank you page
  4. While such a simple approach is not able to handle multipage forms and i see no problem in that. Whenever a multipage form is really needed it either justifies a dedicated package or a frontend application to help users with direct feedback.

There are still many details unclear, it might even makes sense to reuse the existing form-finishers and but get rid of the runtime and the configuration.

My initial reaction is: “Why?”
IMO that approach would come with (mostly) needless complexity (and some historic weirdness) of our MVC stack.
Instead I would suggest to separate validation and form handling and create dedicated interfaces/classes for that. Maybe using some kind of middleware-like chain so that you can add more handlers easily.

That would also pave the way for further extensions like support for multi-page forms

Maybe i misphrased that. The most valuable parts are indeed validation and data-handling and i hope to find a much simpler architecture if we separate those aspects. Wether the logic around that is a controller or not is not that important to me. But i really would like to end up with a much easier solution.

Also what would like to achieve eventually is a seperation of the three main concerns of a form: 1. rendering, 2. validation and 3. data-handling. Currently all three aspects are defined togehter in forms.yaml with rendering and validation beeing defined with the exact same dataStructure.

While i see the advantage of this beeing possible (especially for form-builder) it makes any definition of custom markup really tedious. Especially defining custom containers for grids or combined fields is surprisingly hard. The result is quite a learning curve for new integrators as some kind of grid is part of almost every form.

I would really like to support a case where the rendering of a form page/fragment/field can be defined by a fusion prototype (using Neos.Fusion.Form) that is easily testable in the styleguide while the Validation and DataHandling is defined on the integration layer probably by some kind of setting.

@bwaidelich in terms of Fusion.Form this could look like this:

type: 'Neos.Form:Form'
identifier: contact
label: 'Contact form'
renderer: Vendor.Site:ContactForm 
validation: 
	firstName: 
		- identifier: 'Neos.Flow:NotEmpty'
	lastName: 
		- identifier: 'Neos.Flow:NotEmpty'
	email:
        - identifier: 'Neos.Flow:NotEmpty'
        - identifier: 'Neos.Flow:EmailAddress'		
finishers:
  ...

Basically replacing renderables optionally with separate renderer and validation configurations. If done on form, page and fragment level this would even be backwards compatible.