Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Livewire Forms Laravel Package

aerni/livewire-forms

Use Statamic form blueprints as a Livewire form builder with real-time validation, one source of truth for rules, reCAPTCHA and honeypot spam protection, display conditions, multi-site labels, and styled views—no client-side validation library needed.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites (check these before installing): a Statamic 5+ site with Livewire wired into the frontend, and a Tailwind build that includes @tailwindcss/forms — the bundled views assume both. If your site is Bootstrap, or Tailwind without the forms plugin, budget time to rewrite the published views rather than expecting them to look right.

composer require aerni/livewire-forms
php please livewire-forms:setup      # wizard: creates a view, theme, optional component
php please vendor:publish --tag=livewire-forms-config   # optional

Where to look first, in order:

  1. config/livewire-forms.php — the default view, default theme, and the models map (Statamic fieldtype → Livewire Forms field model). This file tells you how the whole addon resolves things.
  2. The published resources/views/vendor/livewire-forms/ directory — the views/, themes/, and per-field views that the directives render.
  3. Your Statamic form blueprint (resources/blueprints/forms/contact.yaml) — this is the actual form definition and the validation source of truth.
  4. Your layout — confirm {{ livewire:styles }} / @livewireStyles and {{ livewire:scriptConfig }} / @livewireScriptConfig are present, or that @formAssets is rendered inside the form view.

First use case: a standard contact form. Define fields and validate rules on the contact form blueprint, then drop one line into the Antlers or Blade template:

{{ livewire:form handle="contact" }}

No controller, no fetch/AJAX handler, no client-side validation library. Submitting validates server-side against the blueprint, shows per-field errors in real time, and writes a Statamic submission. That is the whole value proposition — verify it end-to-end on day one before building anything custom on top.

Implementation Patterns

Blueprint-as-source-of-truth loop. The daily workflow is: edit the YAML blueprint (add a field, change a validate rule, reorder), reload the page, done. Because views are rendered from the blueprint, adding a field never requires touching the template. This is the pattern to lean on — resist the urge to hardcode markup for every field. Keep display strings, instructions, and placeholders in the blueprint so multi-site translation keeps working.

Per-form views and themes, with granular fallback. Resolution is layered: view and theme props override config defaults; otherwise the form's handle is used to autoload contact.blade.php and a contact theme. Theme fallback happens per view, not per theme — you can override just fields/radio.blade.php and inherit everything else. Practical convention: one shared theme for the design system, one per-form view only when layout genuinely differs (a newsletter inline form vs. a full contact page).

Partial override instead of full custom markup. Prefer @formSection('contact_information') and @formField('name') over rebuilding the form by hand. Property overrides keep you on the blueprint while tweaking presentation:

@formField('name', ['display' => 'Your Name', 'tooltip' => 'Full name, please'])

You can also point a single field at a custom view via view: in the blueprint, or by naming the view after the field handle — useful for one-off widgets (a fancy radio group for subscription) without forking the theme.

Custom component when the blueprint isn't enough. Generate with php please livewire-forms:component ContactForm; it autoloads by handle when the class name ends in Form. Load it explicitly (<livewire:contact-form :my-custom-prop="$value">) when you need to pass data in. Two hooks carry most of the work:

public function mountedFields(Collection $fields): void
{
    $fields->get('name')->display('Your name');
}

public function formSubmitted(Submission $submission): void
{
    // runs before Statamic processes the submission — enrich it here
    $submission->set('entry_title', $submission->augmentedValue('entry')->value()->title);
}

Dynamic field data: model vs. hook. For a select populated from a collection, either swap the model (protected array $models = ['products' => \App\Fields\SelectProduct::class]) and override optionsProperty(), or mutate options in mountedFields. Use a model when the logic is reusable across forms; use the hook when it's a one-off. Remember the naming contract: any public method ending in Property becomes a field property.

Submission side-effects: use the right event. The formSubmitted hook is for mutating the submission. For anything else (CRM push, Slack, analytics), listen to Statamic\Events\FormSubmitted server-side, or $wire.on('form-submitted', ...) client-side. Keep Statamic's own form notifications configured on the form for email — the addon doesn't replace that.

Success UX. Use the redirect prop for thank-you pages, or render a success view for inline confirmation. Guard against double-submits in whatever you add.

Asset bundling. If you use Vite to bundle Livewire/Alpine manually, import livewire-forms.js + .css (full bundle) or the individual form.js + filepond.js + grecaptcha.js modules, then remove @formAssets from your form views.

Gotchas and Tips

  • The Tailwind dependency is real. Unstyled markup is almost always a missing @tailwindcss/forms plugin, not a broken install. Check this first.
  • Double-loading assets. Manual bundling plus @formAssets gives you two Livewire/Alpine instances and bizarre, hard-to-trace behaviour. Remove the directive.
  • Published views are forks. The README explicitly warns that future releases may change view structure and you'll have to update manually. Pin the version, and diff your published views against the vendor copy on every upgrade. This is the biggest long-term maintenance cost.
  • Autoloading contracts are silent. Component classes must end in Form; views/themes autoload by handle; field views autoload by field handle before the type. A typo doesn't error — it silently falls back to the default. When a customisation "doesn't apply," suspect the naming, then clear compiled views (php please stache:clear / view cache).
  • Validation is only as good as the blueprint. Simple per-field rules translate cleanly; cross-field conditional validation (required_if, rules depending on another field's value) is where you'll feel friction. Use a custom component and add rules to the Livewire component rather than contorting the blueprint.
  • handle is required, including when dynamic. {{ livewire:form :handle="field:handle" }} blows up if the field is empty — guard the render.
  • Honeypot false positives. Autofill and password managers happily fill hidden fields and silently drop legitimate submissions. Test with a real browser profile, and exclude the honeypot from autofill (autocomplete="off", tabindex="-1").
  • reCAPTCHA is v2 (checkbox), not v3. Keys are per-site and need configuring for local/dev; don't assume it's drop-in across multi-site setups without separate keys.
  • File uploads need a disk. Filepond temp uploads depend on your filesystem config; test on the real target disk (S3 vs. local) early — this is a common late-stage surprise.
  • Hook ordering matters. formSubmitted runs before the Statamic FormSubmitted event, so mutations made in the hook are visible to your listeners. Put enrichment in the hook, side-effects in the listener.
  • Debugging order of operations: is the form blueprint actually registered (php please stache:clear)? Is the Livewire component resolving to the right view/theme (dump $field->view)? Did form-submitted fire (browser listener / Livewire devtools)? Is the submission in storage/forms/? That sequence finds most issues fast.
  • Maturity risk, priced in. 29 stars, zero dependents, a NOASSERTION license, and a release date that looks wrong. Verify the license before commercial use, pin the version, and assume you may be the one fixing edge cases — no community answers to fall back on. The extension points (config models map, custom components, theme overrides) are clean enough that this is manageable, but it's not a package to adopt casually into a long-lived client site without a fallback plan of hand-rolling the Livewire form yourself.
  • Unsupported fieldtype? Don't patch the vendor directory. Create a model extending the closest existing one, implement the *Property methods, and bind it in config/livewire-forms.php — that's the intended escape hatch.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels