sumanahmed / dynamic-form-builder
Generic, pluggable dynamic form builder for Laravel (form builder + submissions + PDF/email export).
Package info
github.com/sumanahmed/dynamic-form-builder
pkg:composer/sumanahmed/dynamic-form-builder
Requires
- php: ^8.3
- barryvdh/laravel-dompdf: ^2.0|^3.0
- illuminate/database: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0
This package is not auto-updated.
Last update: 2026-08-03 18:01:59 UTC
README
Generic, pluggable dynamic form builder for Laravel, extracted from a domain-specific
"Custom Form" feature. Keeps the jQuery-based drag/drop builder UI, but every field type
is now a plugin instead of a hardcoded if ($parentFieldType == N) branch.
Install
composer require sumanahmed/dynamic-form-builder php artisan vendor:publish --tag=dynamic-form-builder-config php artisan vendor:publish --tag=dynamic-form-builder-assets php artisan migrate
Built-in field types (registered by default in config/dynamic-form-builder.php):
input, select, radio, checkbox, textarea.
Adding a new field type (addon)
Domain-specific field types are not part of the core package. They can ship as separate Composer packages that:
- Implement
DynamicFormBuilder\Contracts\FieldType(or extendAbstractFieldType) — defines validation rules, default settings, and how a submitted value renders as text (for the PDF export). - Ship a small JS file that calls
DynamicFormBuilder.registerFieldType('key', {...})— defines the builder editor markup and how to read it back into a payload. - Register their
FieldTypeclass in the host app'sconfig('dynamic-form-builder.field_types')array. - Add one
<script>tag for their published JS file in the builder Blade view (or override the vendor view once, and it's automatic after that).
No core file changes, no core migration changes — new field-type-specific config
lives in the form_fields.settings JSON column, not a dedicated column.
What moved where (mapping from your original code)
| Original | Now |
|---|---|
CustomFormController |
FormBuilderController |
CustomFormService |
FormBuilderService + FormSubmissionService |
CustomForm |
Form |
CustomFormType |
FormField (field_type is now a string registry key) |
CustomFormDetails |
FormFieldOption |
CustomFormValue / formValueDetails |
FormSubmission / FormSubmissionValue |
CustomFormEmail |
FormRecipient |
CustomFormParentFieldType table |
FieldTypeRegistry (PHP, config-driven) |
Hardcoded JS if (parentFieldType == 6) etc. |
DynamicFormBuilder.registerFieldType(key, impl) |
getFieldDetailsValue() in the controller |
FieldType::formatValueForDisplay() per type |
Still to migrate over from your original code (left for you to port)
- Permission gate names/wiring to your real permission package (Spatie assumed).
- Notification hook (
notifyUser) — add aFormBuilderService::notify()call or an event (FormCreated,FormUpdated,FormDeleted) the host app listens to. - A data migration script to move existing
custom_form*tables into the new generic tables (mapparent_field_typeint → field type string key).