tivents/livewire-form-builder
Installation
composer require tivents/livewire-form-builder
php artisan vendor:publish --tag=livewire-form-builder-config
php artisan livewire-form-builder:publish-stubs
config/livewire-form-builder.php and app/Repositories/FormRepository.php are published.Define a Form Create a form definition in a Livewire component:
use Tivents\LivewireFormBuilder\Contracts\FormRepositoryContract;
use Tivents\LivewireFormBuilder\Components\FormBuilder;
public function mount(FormRepositoryContract $formRepository) {
$this->form = $formRepository->getForm('contact_form');
}
public function render() {
return view('livewire.form-builder', [
'form' => $this->form,
]);
}
Create a Form via UI
/form-builder (route defined in routes/web.php after publishing).text, email, submit) onto the canvas.database/forms table by default).Render the Form
Use the FormBuilder component in a Blade view:
<livewire:form-builder :form="$form" />
Handle Submissions
Implement FormRepositoryContract to process submissions:
public function storeSubmission(array $data) {
// Save to your model (e.g., Contact::create($data))
}
Form Design
/form-builder route to visually design forms.row fields to create responsive grids (e.g., 1/2 columns for side-by-side fields).Dynamic Form Rendering
<livewire:form-builder
:form="$form"
wire:model="submissionData"
@submitted="handleSubmission"
/>
required|email) are applied per-field without manual JS.Conditional Logic
phone field if country is 'US'").wire:ignore and Alpine.js.Submission Handling
FormRepository to map submissions to your models:
public function storeSubmission(array $data) {
YourModel::create($this->mapData($data));
}
$this->form->exportSubmissionsToCsv();
Repeater Groups
repeater field to create dynamic nested forms.resources/views/vendor/livewire-form-builder/fields directory./form-builder via middleware:
Route::middleware(['auth'])->group(function () {
Route::get('/form-builder', [FormBuilderController::class, 'index']);
});
$form->exportToJson(); // Save to storage
FormRepository::importFromJson($json);
Repository Contract Misalignment
FormRepositoryContract methods (e.g., getForm, storeSubmission).php artisan livewire-form-builder:publish-stubs and extend the stubbed FormRepository:
class FormRepository implements FormRepositoryContract {
public function getForm(string $formId) { ... }
public function storeSubmission(array $data) { ... }
}
Conditional Logic Not Updating
wire:key is unique for conditional fields and that Alpine.js is loaded:
@push('scripts')
@livewireScripts
<script src="//unpkg.com/alpinejs" defer></script>
@endpush
File Upload Paths
upload_disk in config/livewire-form-builder.php:
'upload_disk' => 'public',
'upload_path' => 'uploads/forms',
Livewire Hook Conflicts
mount) interfere with form rendering.protected $listeners or protected $rules in your Livewire component to avoid naming collisions.storage/logs/laravel.log for FormRepository errors.forms table.dd($this->submissionData) in the component to debug submitted data.// In a browser console (for testing):
document.querySelectorAll('[x-data]').forEach(el => {
el._x = { data: {}, effects: [] };
});
Custom Field Types
php artisan vendor:publish --tag=livewire-form-builder-views
app/Fields/CustomField.php) and register it in the config:
'fields' => [
'custom' => \App\Fields\CustomField::class,
],
Override Default Views
resources/views/vendor/livewire-form-builder/ to your project and modify templates (e.g., form-builder.blade.php).Artisan Commands
php artisan make:livewire-form-builder-command
app/Console/Kernel.php:
protected $commands = [
\Tivents\LivewireFormBuilder\Console\Commands\PublishStubs::class,
\App\Console\Commands\CustomFormCommand::class,
];
Database Schema
forms and form_fields tables by publishing migrations:
php artisan vendor:publish --tag=livewire-form-builder-migrations
database/migrations/xxxx_create_forms_table.php before running migrate.How can I help you explore Laravel packages today?