Form Builder is a Laravel package built on top of Filament v4, allowing you to visually build and manage dynamic forms from your admin panel.
It lets you attach custom forms to any Eloquent model in your application with minimal setup.
- Built entirely with Filament v4 components
- Dynamic form rendering using
form_content+form_response - All form fields are stored in a single JSON column
- Visually design sections + fields with nested repeaters
- Automatically bind values via
custom_id - Smart versioning support (
form_version) - Seamlessly plug into any Eloquent model using a trait
- Custom Filament resource base for auto-form handling
- Install via
form-builder:installcommand
Requires Laravel 12+ and Filament 4+
composer require dayne-valourite/form-builderphp artisan form-builder:installThis will:
- Publish the config file to
config/form-builder.php - Run the required database migrations
In your PanelProvider:
use Valourite\FormBuilder\FormBuilderPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FormBuilderPlugin::make(),
]);
}Use the HasFormBuilder trait:
use Valourite\FormBuilder\Concerns\HasFormBuilder;
class Client extends Model
{
use HasFormBuilder;
}This enables:
form_idform_contentform_responseform_version
No need to add these to
$fillable.
Note: Ensure your model has those columns
- We can update the column names by implementing the following functions:
public static function getFormContentColumn(): string
public static function getFormIdColumn(): string
public static function getFormResponseColumn(): string
public static function getFormVersionColumn(): stringuse Valourite\FormBuilder\Filament\Resources\FormBuilderResource;
class ClientResource extends FormBuilderResource
{
protected static string $model = \App\Models\Client::class;
/**
* Optional: Define your base schema fields
* If omitted, these will be auto-generated from `$fillable` and `$casts`
*/
public static function customSchemaFields(): array
{
return [
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
];
}
/**
* Optional: Define your base infolist schema fields
* If omitted. these will be auto-generated from `$fillable` and `$casts`
*/
public static function customInfolistFields(): array
{
return [
TextEntry::make('name'),
TextEntry::make('email'),
];
}
}use Valourite\FormBuilder\Filament\Pages\FormBuilderCreateRecord;
class CreateClient extends FormBuilderCreateRecord
{
protected static string $resource = ClientResource::class;
}This handles:
- Dynamic rendering of the form schema
- Saving the form response into
form_response - Linking the correct
form_id, version, and structure
And inside your Edit page class
use Valourite\FormBuilder\Filament\Pages\FormBuilderEditRecord;
class EditClient extends FormBuilderEditRecord
{
protected static string $resource = ClientResource::class;
}This handles:
- Dynamic rendering of the form schema
- Allowing updates to be made to the form values
- Selecting a form from the dropdown dynamically renders its fields
- Values are bound using each field’s
custom_id - Saved response values are stored as
form_response[field_id] => value form_contentis stored alongside the record for replay/version safety
In config/form-builder.php:
return [
'models' => [
App\Models\Client::class,
App\Models\Project::class,
],
'versioning' => [
'mode' => 'increment', // or 'clone'
'auto_increment' => true,
],
];Pull requests, issues, and improvements are welcome!
To test form saving logic:
$this->assertDatabaseHas('clients', [
'form_response' => json_encode([...]),
]);- Attach forms to any model
- Store form definitions in DB
- Save submissions as JSON
- Versioning support (increment/clone)
- Better handling of form creation without page extending
- More Fields
- Multi-page/wizard forms
MIT © Dayne Valourite