Forms

Plume provides a comprehensive set of form components and a powerful Alpine.js plugin to manage state, validation, and AJAX submissions.

The Form Plugin

The x-plume::form component is a powerful bridge between Blade and Alpine.js. It automatically handles state management, AJAX submissions, CSRF protection, and UI feedback for success/error states.

Standard Usage

Handling state management, AJAX submissions, and CSRF protection automatically.

User Information

Please fill out the form below.

We'll never share your email.

blade
<x-plume::form action="#"
    formData="{ 'first_name': '', 'last_name': '', 'email': '', 'password': '' }"
    submitButton="Register" >
    <x-plume::form.section title="User Information" description="Please fill out the form below."
        :minCols="1" :maxCols="2">
        <x-plume::form.input label="First Name" model="first_name" placeholder="John" />
        <x-plume::form.input label="Last Name" model="last_name" placeholder="Doe" />
    </x-plume::form.section>

    <x-plume::form.section>
        <x-plume::form.input label="Email Address" model="email" type="email"
            placeholder="you@example.com" icon="icon-[fluent--mail-24-regular]">
            <x-slot:after>
                <p class="text-sm text-foreground/50 dark:text-background-400">We'll
                    never share your email.</p>
            </x-slot:after>
        </x-plume::form.input>
        <x-plume::form.password label="Password" model="password" />
    </x-plume::form.section>
</x-plume::form>

Alpine.js State & Helpers

The plugin exposes reactive properties within the form's scope:

  • data: Contains all user input fields.
  • processing: True while an AJAX request is in flight.
  • isDirty: True if current data != saved state.
  • wasSuccessful: True after success.
  • hasFailed: True if errors returned.
  • getError(field): Returns the first error message.

Server Response

Use the PlumeResponse class in your controllers:

php
use deokon\Plume\Http\Responses\PlumeResponse;

public function store(Request $request) {
// ... validation ...
return PlumeResponse::success('Saved!', $data);
// OR
return PlumeResponse::error('Failed', $errors);
}

Examples

Mixed Inputs

Showing off selects, toggles, and more.

Preferences

Customize your experience.

Enable Notifications

Options

blade
<x-plume::form action="#" 
    formData="{ fruit: 'apple', notifications: true, terms: false, quantity: 5, birth_date: '' }">
    <x-plume::form.section title="Preferences" description="Customize your experience.">
        <x-plume::form.select label="Favorite Fruit" model="fruit">
            <option value="apple">Apple</option>
            <option value="banana">Banana</option>
            <option value="orange">Orange</option>
        </x-plume::form.select>

        <x-plume::form.toggle label="Enable Notifications" model="notifications" />

        <x-plume::form.group label="Options">
            <x-plume::form.checkbox model="terms">
                I agree to receive marketing emails
            </x-plume::form.checkbox>
        </x-plume::form.group>

        <div class="grid grid-cols-2 gap-4">
            <x-plume::form.number label="Quantity" model="quantity" min="1" max="10" />
            <x-plume::form.date label="Birth Date" model="birth_date" />
        </div>
    </x-plume::form.section>

    <x-plume::form.actions>
        <x-plume::button type="submit">Save Preferences</x-plume::button>
    </x-plume::form.actions>
</x-plume::form>

Inline Form

blade
<x-plume::form inline action="#" 
    formData="{ email: '', password: '' }" submitButton="Login">
    <x-plume::form.input label="Email" model="email" placeholder="Email" class="sm:w-64" />
    <x-plume::form.password label="Password" model="password" placeholder="Password"
        class="sm:w-64" />
</x-plume::form>

Properties

Form

Prop Type Default Description
action string '' Submission URL. Auto-detected if using a <form> tag.
method string 'POST' HTTP method (GET, POST, PUT, PATCH, DELETE).
formData array|string|null null Initial reactive data. Pass a PHP array or use Js::from().
submitButton string null Label for an automatic primary submit button with a loader.
resetButton string null Label for an automatic reset button.
hideOnSuccess bool false Whether to hide the form content after a successful submission.
resetOnSuccess bool false Whether to reset the form data to initial state after success.
onSuccess string null AlpineJS expression or callback function to execute on success.
onError string null AlpineJS expression or callback function to execute on error.
showAlerts bool true Whether to automatically show success/error alerts.
inline bool false Renders form elements in a horizontal flex layout.

Section

Prop Type Default Description
title string null The section title.
description string null Optional text to describe the section's purpose.
minCols int 1 Number of columns on small screens.
maxCols int null Number of columns on large screens. Defaults to minCols if not set.

Usage

Input with Icon and Help Text

blade
<x-plume::form >
    <x-plume::form.input label="Email" model="email" type="email"
        icon="icon-[fluent--mail-24-regular]">
        <x-slot:after>
            <p class="text-xs text-foreground/50 dark:text-background-400">We'll never share your
                email.</p>
        </x-slot:after>
    </x-plume::form.input>
</x-plume::form>

Form Section

blade
<x-plume::form >
    <x-plume::card title="Profile" description="Update your info.">
        <x-plume::form.section>
            <x-plume::form.input label="Name" model="name" />
        </x-plume::form.section>
    </x-plume::card>
</x-plume::form>

Dusk Test Form

blade