Form Components

Form components provide consistent input handling and validation display.

Available Components

Input Fields

Text Input

<x-form.input
    name="title"
    label="Title"
    :value="old('title', $item->title ?? '')"
    required
/>

Email Input

<x-form.input
    type="email"
    name="email"
    label="Email Address"
    placeholder="user@example.com"
/>

Number Input

<x-form.input
    type="number"
    name="quantity"
    label="Quantity"
    min="0"
    step="1"
/>

Select Dropdown

<x-form.select
    name="country_id"
    label="Country"
    :options="$countries"
    :selected="old('country_id', $item->country_id ?? '')"
    required
/>

Textarea

<x-form.textarea
    name="description"
    label="Description"
    :value="old('description', $item->description ?? '')"
    rows="5"
/>

Markdown Editor (Livewire)

The markdown editor provides a rich editing experience with live preview and help guide, powered by Livewire for server-side rendering:

<x-form.markdown-editor-livewire
    name="description"
    label="Description"
    :value="old('description', $item->description ?? '')"
    rows="6"
    helpText="Use Markdown formatting. Preview updates in real-time."
    required
/>

Features:

Props:

Implementation:

Checkbox

<x-form.checkbox
    name="is_active"
    label="Active"
    :checked="old('is_active', $item->is_active ?? false)"
/>

Error Display

Validation errors are automatically displayed:

<x-form.input name="email" label="Email" />
{{-- Error will show if validation fails --}}

Manual error display:

<x-form.error name="email" />

Form Patterns

Standard CRUD Form

<form method="POST" action="{{ route('item.store') }}">
    @csrf

    <x-form.input
        name="internal_name"
        label="Internal Name"
        required
    />

    <x-form.select
        name="partner_id"
        label="Partner"
        :options="$partners"
        required
    />

    <x-form.textarea
        name="description"
        label="Description"
    />

    <div class="flex gap-2">
        <x-button type="submit" color="green">
            Save
        </x-button>
        <x-button-link :href="route('item.index')" color="gray">
            Cancel
        </x-button-link>
    </div>
</form>

Form with Livewire

<form wire:submit="save">
    <x-form.input
        wire:model="title"
        name="title"
        label="Title"
    />

    <x-form.select
        wire:model="category"
        name="category"
        label="Category"
        :options="$categories"
    />

    <x-button type="submit" wire:loading.attr="disabled">
        <span wire:loading.remove>Save</span>
        <span wire:loading>Saving...</span>
    </x-button>
</form>

Validation Display

Field-Level Errors

Errors display automatically beneath fields:

<x-form.input name="email" label="Email" />
{{-- If validation fails, error appears here --}}

Summary Errors

Display all errors at the top of the form:

@if ($errors->any())
    <div class="bg-red-50 border border-red-200 text-red-800 rounded-lg p-4 mb-4">
        <h3 class="font-semibold mb-2">Please correct the following errors:</h3>
        <ul class="list-disc list-inside">
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Best Practices

  1. Use consistent naming - Match form field names to model attributes
  2. Always include labels - For accessibility and clarity
  3. Handle old input - Use old() helper for form repopulation
  4. Show validation errors - Display errors near relevant fields
  5. Disable submit on processing - Prevent double submissions