I am currently working on a formbuilder app for XP (6.x), and thought I should start this thread to share progress and get feedback and suggestions.
As I understand it, Enonic is also working on an app like this, which is ETA mid -16 ( http://ow.ly/TXYAz ).
I hope to finish mine by the end of -15, but since it is a hobby-project done in my spare time, it might take longer.
Main features/first release
Create any input type (implemented as individual content types) <- Finished
Add any legal attributes to the input elements <- Finished
Can be used in two ways:
A stand-alone page (part using “form” content data) <- Finished
Included in any page (form set up in the part) <- Finished
Do (almost) any kind of validation <- In progress
Dynamic UI: Configure fields to display/hide based on user input <- Not yet implemented
Bootstrap (adding Bootstrap classes and requiring bootstrap CSS and JS to be included in page) <- In progress
Custom styling for this app <- Not yet implemented
No styling/browser defaults <- Finished
Planned for the future
- Import values (e.g. through URL params)
- Implement common validation methods, like
- (localized) phone number
- Norwegian security number
- Server-side validation
- Some OWASP security protection (against e.g. SQL injection-attacks)
- +++ (I am taking suggestions)
I would love suggestions and tips if you have any ideas on what to do/what not to do.
@tsi: To answer your question “Are you using node api or content api?” in another thread, I believe I am using the content api, but am a little unsure about the difference.
I am using content types for all the elements, and generating the form in a part. (Actually two parts: I have one which uses a form content type as input, and one where the form is configured in the actual part.)
One question: I am currently adding attribute-configuration to the input types as mixins, so each attribute can be reused in several input types. (So the configuration is consistent throughout the app)
- Will this give a performance hit relative to configuring the attributes directly in the content type? My installation has been running a bit slow lately, but that may have other (external) causes as well.
I have also thought about implementing the input types as separate parts (so the editor can drag-and-drop them on the page). However, I came to the conclusion that I would lose some flexibility by doing so, as the form or page would then have to contain the form-configuration (and generate the form tag). And it is still possible to move input fields around by using the drag-and-drop feature on the content selector-list.
Since my goal is to generate forms that can be used anywhere (in page types not known to the app), I decided against this, but may look into it again when finished with the first and second version.
Vegard - are you aware of the “unstructured” content type?
Some ideas for your formbuilder (given that I have not misunderstood the description above)
- look into defining your own custom form definition format, and optionally store this in a “vegardForm” content type or similar. This way forms can be defined without deploying new content types…
- Store the responses as “unstructured” data for max flexibility
U have a screenshot - not sure if I understand the approach completely?
Hmm, I am aware of the “unstructured” content type, but so far have not found a use case for it. Do you mean I could save the responses as the “unstructured” content type, or define/build the form as “unstructured” type? Do you have an example where this content type is used?
As for “defining your own form definition format”, do you mean building my own content type?
So far, I have not thought too much about receiving/storing the data. Often, the responses will be sent to another system altogether, but I agree that at least having the option of storing the responses is a good idea.
This is a screenshot (I am currently refactoring a bit, so not everything is working atm) I took just now:
Does that cover what you wanted to see?
So do you have a single content-type “input” and multiple contents (one for each widget), or is there one content type per input (with content items for each variation?)
Anyway, I would probably recommend you to create a “form” content type, and then create the form as a standalone content, and when finished have a form part you place on the desired page, then select the form to use in that part.
For unstructured, yes - indeed you should consider storing the responses as unstructured (and maybe in the future as nodes directly).
I have one content type for each input type, so that the content type determines what attributes are available, and how it is rendered. This is more of a hassle in 4.x, as you would need a separate folder for each input type, but I have done something similar (smaller scale) there as well.
Unless even more dynamic form-creation is implemented (e.g. if you select one option from a dropdown, show some input fields, while if you select another you show some other fields), I consider this the cleanest approach.
For now, I have the following elements:
I haven’t quite decided what to do with submit/reset buttons. I think those should be configured as part of the form, as there really only should be one (max) of each. I have hidden inputs as a content type, but still struggle a bit with those - generally (at least on my part) they are used for system-supplied values, which means I need to implement some general way of importing those values.
I guess you approach with the “form” content type is somewhere in the middle of my two approaches:
- The “content” approach uses a form content, which has a connected page template, so it is rendered as a full-page form
- The “part” approach has the configuration in the part, thus skipping the “form” content. I started using this because I thought “when do you really want the exact same form in multiple places on your site?”
I will test the approach you recommend as well, and see what works best.
And I will definitely implement storage using unstructured content. However, I will keep this as an option, as I suppose the data will often be expected to be sent somewhere else than Enonic entirely. (Some third-party system) That is the reason I have so far only planned for providing a URL to the receiving end. Having a built-in solution would be great, though, so I will add this to my feature list.
Note to self: Planning this approach, I guess implementing some reporting-tool should also be a feature.
Great work Vegard! We look forward to the release
@tsi: I tried saving the response as unstructured content tonight, and that worked fine.
I added the option of setting a save-folder to the form-config, so that forms can be stored in separate folders and I don’t have to make assumptions about the site structure.
However, I am now facing another problem: I need to generate some unique name for the content.
I could use the form id and a timestamp (and alternatively some random number on top) to reduce the risk of getting duplicates, but I would rather generate a truly unique ID.
Does that kind of functionality exist in XP?
I tried not setting the name, but that produced an error…
The name will be autogenerated soon, not sure if actually made it into 6.2, but will for sure be in 6.3
For now, just generate a name, using title + date for instance?
I love how many times lately I have thought “wouldn’t it be great if Enonic implemented feature X?”, and then you are one step ahead and almost ready to release it when I ask for it…
Interesting approach =) Looks really nice, cool that you’re working on this!
Have you thought about the “meta”-style approach? Where you have a form content type and in that a item-set for each field with a drop down for selecting type so that display is handled correctly, and then a unstructured content type for storing the data? I’m asking just because I thought about this myself for a project and wondered if you have seen any disadvantages that I’ve yet to see.
I guess that is what TSI was into. With the form CTY as a “master”.
A very big advantage I see on your approach is that you can store common fields as content and re-use them on multiple forms. My idea with the “meta” item-set doesn’t support this.
Hi, Bobby. Sorry for the late response.
I considered the “meta”-style approach you describe, with using a field-set for the input fields and a dropdown for selecting type. However, I decided to discard it, for the following reasons:
The advantages with the “meta”-approach is keeping everything together, and being able to create the form “in one sitting”. (Not having to create each input separately and then adding them to the form)
However, I found the disadvantages to outweigh the advantages. First and foremost, this would require me to either:
- Have each attribute available for each input type. I decided this would be confusing - e.g. how would you handle a step-attribute on a date input field?
- Or use generic attibute inputs that would be mapped to different attributes based on the selected input type.
Also, as you said, it would not be possible to re-use the input fields. One might end up with many different “implementations” of e.g. a “fødselsnummer”-input (ssn), which is something I wanted to avoid. I prefer to streamline as much as possible. Also, the approach I chose will enable creation of new forms more quickly, as most of the input-fields will probably already exist.
I basically couldn’t choose between using the form-part as parent or a “form” content type as parent, so I am going the Winnie the Pooh-way and doing both. That way others can choose themselves, and eventually one will probably show itself to be better suited.
Thanks for your insights! I see the advantages and disadvantages too now that you shared your findings.
Keep up your work and good luck!
Better late than never, right?
I just published the first version of the form builder on [GitHub].
I still have a lot of features left to implement, but it is possible to create basic forms, using either Bootstrap, browser defaults or a custom styling I implemented. (Please don’t blame me for my poor design skills!)
The next features I’ll add is more validation and showing/hiding parts of the form based on user input.
Please feel free to review, use, critique or submit pull requests!
Btw, there are a couple of known bugs:
- The range input doesn’t work with the Bootstrap theme,
- I hope to fix this quickly. I just forgot to update the template to the latest model changes.
- Multiple-file upload without Ajax (that is, by using default post action) fails.
- I have fixed this for the Ajax submit functionality.
- This seems to be a bug in XP. I’ll add a separate bug topic for this.
Impressive work here! Just browsed through the code, there’s a lot of it here. Many things to consider and handle. Interesting use of mixins.
Will need to take this for a spin soon.
@it_vegard The upload bug with multiple files (or in general multipart POST with duplicated fields) is already fixed in 6.4.
It will be released very soon this week.
Exiting stuff - just tried compiling - but it failed?:
$ ./gradlew deploy
Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain