filaforms.app
Advanced

Standalone Components

Use the form builder and renderer as standalone Livewire components without a Filament panel.

FilaForms ships two standalone Livewire components that work without the Filament admin panel or database. Use them to embed form building and rendering anywhere in your Laravel application.

Form Builder

The visual drag-and-drop form builder as a standalone Livewire component.

Basic Usage

resources/views/my-page.blade.php
{{-- Empty builder --}}
<livewire:filaforms::form-builder />

{{-- Pre-populated with an existing schema --}}
<livewire:filaforms::form-builder :form-schema="$existingFormJson" />

Capturing Form Data

The builder emits a form-updated Livewire event whenever the user makes changes. Listen for this event to capture the current form state:

app/Livewire/MyFormManager.php
use Livewire\Attributes\On;
use Livewire\Component;

class MyFormManager extends Component
{
    public ?array $formData = null;

    #[On('form-updated')]
    public function onFormUpdated(array $formData): void
    {
        $this->formData = $formData;
    }

    public function save(): void
    {
        DB::table('my_forms')->insert([
            'form_json' => json_encode($this->formData),
            'created_at' => now(),
        ]);
    }

    public function render()
    {
        return view('my-form-manager');
    }
}
resources/views/livewire/my-form-manager.blade.php
<div>
    <livewire:filaforms::form-builder />

    <button wire:click="save">Save Form</button>
</div>
The builder does not include a save button. You add your own and decide when to persist the form data.

JSON Form Structure

The builder outputs a JSON structure with sections, fields, and settings:

{
    "id": "01HZXF1A2B3C4D5E6F7G8H9J0K",
    "name": "Customer Feedback Form",
    "settings": {
        "experience": {
            "display_mode": "simple",
            "submit_button_text": "Send Feedback",
            "success_message": "Thank you!"
        }
    },
    "schema": {
        "sections": [
            {
                "id": "01HZXF2B3C4D5E6F7G8H9J0KL",
                "code": "personal_info",
                "name": "Personal Information",
                "type": "section",
                "active": true,
                "sortOrder": 0,
                "settings": {},
                "fields": [
                    {
                        "id": "01HZXF3C4D5E6F7G8H9J0KLM",
                        "code": "full_name",
                        "type": "text",
                        "label": "Full Name",
                        "active": true,
                        "sortOrder": 0,
                        "width": "100",
                        "validationRules": [],
                        "settings": {},
                        "options": []
                    },
                    {
                        "id": "01HZXF4D5E6F7G8H9J0KLMN",
                        "code": "email",
                        "type": "email",
                        "label": "Email Address",
                        "active": true,
                        "sortOrder": 1,
                        "width": "100",
                        "validationRules": [],
                        "settings": {},
                        "options": []
                    }
                ]
            }
        ]
    }
}

The schema is structured into three top-level keys:

KeyPurpose
settings.experienceDisplay mode, button labels, submission behavior
schema.sectionsOrdered sections, each containing fields
id, nameForm identification

All experience settings use snake_case keys (e.g., display_mode, submit_button_text). See Experience Settings for the full list.

Form Renderer

Render forms from JSON or a database record without any admin panel.

From JSON Schema

resources/views/form.blade.php
<livewire:filaforms::form-renderer :form-schema="$formSchema" />

From Database Record

resources/views/form.blade.php
@php
    $form = \FilaForms\Core\Models\Form::where('slug', 'contact-us')->first();
@endphp

@if($form)
    <livewire:filaforms::form-renderer :form-record="$form" />
@endif

Prefilling Fields

Pass an initialData array to prefill form fields with values. Keys are field codes, values are the prefill data:

resources/views/form.blade.php
<livewire:filaforms::form-renderer
    :form-record="$form"
    :initial-data="[
        'full_name' => $user->name,
        'email' => $user->email,
        'company' => $user->company_name,
    ]"
/>

This works with both database records and JSON schemas:

resources/views/form.blade.php
<livewire:filaforms::form-renderer
    :form-schema="$formSchema"
    :initial-data="['source' => 'landing-page']"
/>

Handling Submissions

The renderer emits a form-submitted event after successful submission:

app/Livewire/PublicFormPage.php
use Livewire\Attributes\On;
use Livewire\Component;

class PublicFormPage extends Component
{
    public string $formSchema;

    #[On('form-submitted')]
    public function handleSubmission(array $submissionData): void
    {
        DB::table('form_submissions')->insert([
            'form_id' => $submissionData['form_id'],
            'data' => json_encode($submissionData['fields']),
            'submitted_at' => now(),
        ]);

        session()->flash('message', 'Thank you for your submission!');
    }
}

Submission Data Structure

{
    "form_id": "01HZXF1A2B3C4D5E6F7G8H9J0K",
    "submitted_at": "2024-01-15T10:30:00Z",
    "fields": {
        "01HZXF3C4D5E6F7G8H9J0KLM": "John Doe",
        "01HZXF4D5E6F7G8H9J0KLMN": "john@example.com"
    }
}

Experience Settings

The settings.experience object controls display mode, submission behavior, and button labels. All keys use snake_case.

KeyTypeDefaultDescription
display_mode"simple" | "wizard""simple"Single page or multi-step wizard
submit_button_textstring"Submit"Label on the submit button
success_messagestringDefault thank-you HTMLMessage shown after submission
one_per_personboolfalseLimit to one submission per visitor
max_submissionsint|nullnullMaximum total submissions allowed
allow_step_navigationbooltrueAllow clicking previous steps in wizard mode
show_progress_barbooltrueShow progress indicator in wizard mode
show_step_numbersbooltrueShow step numbers in wizard progress bar
next_button_textstring"Next"Label on wizard next button
previous_button_textstring"Previous"Label on wizard previous button
Additional settings are available for redirects, custom CSS/JS, and layout. See FormExperienceData for the complete list of properties.

Wizard Mode

To render a standalone form as a multi-step wizard, set display_mode to "wizard". Each section in the schema becomes a wizard step.

{
    "settings": {
        "experience": {
            "display_mode": "wizard",
            "submit_button_text": "Submit Application",
            "allow_step_navigation": true,
            "next_button_text": "Continue",
            "previous_button_text": "Go Back"
        }
    },
    "schema": {
        "sections": [
            {
                "id": "sec_1",
                "code": "personal_info",
                "name": "Personal Information",
                "description": "Tell us about yourself",
                "type": "section",
                "active": true,
                "sortOrder": 0,
                "settings": {},
                "fields": []
            },
            {
                "id": "sec_2",
                "code": "experience",
                "name": "Work Experience",
                "description": "Your professional background",
                "type": "section",
                "active": true,
                "sortOrder": 1,
                "settings": {},
                "fields": []
            }
        ]
    }
}

Each section's name becomes the step title and description becomes the step subtitle. Validation is enforced per step -- the respondent must pass all field validations on the current step before advancing.

Storage Options

You control where form JSON is stored. Common patterns:

// Database table
DB::table('my_forms')->insert([
    'form_json' => json_encode($formData),
    'created_by' => auth()->id(),
]);

// JSON file
Storage::put("forms/{$formId}.json", json_encode($formData));

// Cache (temporary)
Cache::put("form:{$formId}", $formData, now()->addHours(24));

Complete Example

A full workflow: admin creates a form with the builder, public visitors fill it out via the renderer.

Step 1: Admin Creates the Form

app/Livewire/FormCreator.php
use Livewire\Attributes\On;
use Livewire\Component;

class FormCreator extends Component
{
    public ?array $formData = null;

    #[On('form-updated')]
    public function onFormUpdated(array $formData): void
    {
        $this->formData = $formData;
    }

    public function save()
    {
        $id = DB::table('my_forms')->insertGetId([
            'json_structure' => json_encode($this->formData),
            'created_at' => now(),
        ]);

        return redirect("/forms/{$id}/preview");
    }

    public function render()
    {
        return view('livewire.form-creator');
    }
}
resources/views/livewire/form-creator.blade.php
<div>
    <livewire:filaforms::form-builder />
    <button wire:click="save">Save Form</button>
</div>

Step 2: Public Visitor Fills the Form

app/Livewire/FormDisplay.php
use Livewire\Attributes\On;
use Livewire\Component;

class FormDisplay extends Component
{
    public int $formId;
    public string $formSchema;

    public function mount(int $formId): void
    {
        $this->formSchema = DB::table('my_forms')
            ->where('id', $formId)
            ->value('json_structure');
    }

    #[On('form-submitted')]
    public function onSubmitted(array $data): void
    {
        DB::table('my_submissions')->insert([
            'form_id' => $this->formId,
            'data' => json_encode($data),
            'created_at' => now(),
        ]);

        session()->flash('success', 'Thank you!');
    }

    public function render()
    {
        return view('livewire.form-display');
    }
}
resources/views/livewire/form-display.blade.php
<div>
    <livewire:filaforms::form-renderer :form-schema="$formSchema" />
</div>
Copyright © 2026