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

Wire Forms Laravel Package

nyoncode/wire-forms

A Laravel Livewire package for building and managing forms with reusable components, validation, and a clean, expressive API for handling fields, submission, and errors in your Livewire applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Fork before you composer require. At zero stars and zero dependents there is no upstream safety net, so the first step is ownership, not installation:

"repositories": [{ "type": "vcs", "url": "[email protected]:yourorg/wire-forms.git" }],
"require": { "nyoncode/wire-forms": "0.1.4" }

Pin the exact version — ^0.x on a pre-1.0 package permits breaking changes in a patch release. Then confirm it actually fits your lockfile:

composer why-not nyoncode/wire-forms 0.1.4

Pay attention to the php, laravel/framework, and livewire/livewire constraints. The Livewire constraint is the one that will hurt later.

Read the source before you trust the README. The package is small enough to read in an afternoon, and there is exactly one question that decides adoption: does the validation path delegate to Illuminate\Validation\Factory, or does it walk the rules itself? Grep for Validator::make, the Rule contract, and how custom rule objects and FormRequest classes are handled. If rules are hand-evaluated anywhere, stop — that is a divergence from Laravel's validator that nobody upstream has a security process to fix. Read in this order:

  1. composer.json — constraints and autoload map.
  2. The Form base class — constructor, lifecycle, rules(), validate(), reset().
  3. Field/props handling — how a field object becomes a Blade view, and whether unknown attributes forward or vanish.
  4. The validation path — see above.
  5. resources/views — what the field components actually emit, especially aria-*, wire:model modifiers, and error output.

First use case: an internal settings screen, not checkout. Five or six text/select fields, one required|email, one conditional field, one submit, one reset. That exercises binding, the validation round trip, error rendering, and reset semantics without putting anything customer-facing at risk.

Day-one spike checklist — confirm all four before writing a second form:

  1. Errors land in the error bag your existing Blade layout already renders.
  2. A failed submit repopulates state without a manual fill().
  3. An unknown prop on a field component fails loudly rather than being silently dropped.
  4. reset() on a create form does not leave the previously edited record's values behind.

The deliverable is a one-page findings note, not merged code. Gate go/no-go on the validator-delegation answer.

Implementation Patterns

Form class is the schema, Livewire component is the controller. Keep the form class a declarative description — fields, rules, labels, layout — and keep authorization, persistence, and side effects in the component or an action class. Form objects that grow a save() method become untestable and unshareable.

// shape, not verbatim API — confirm signatures against src/
final class ProfileForm extends Form
{
    public function fields(): array
    {
        return [
            Field::text('name')->rules('required|string|max:120'),
            Field::email('email')->rules('required|email'),
            Field::select('timezone')->options($this->timezones())->rules('required'),
        ];
    }
}

One form class per resource, shared between create and update. This is the package's real day-to-day payoff: same rules and layout, different hydration. Mount the form with no data for create, mount it with the model's attributes for update, and your screens stay in sync for free.

Put an adapter seam in front of it on day one. One directory — App\Forms\* base classes, or your own wrapper Blade components that delegate to wire-forms. Roughly a day of work. The payoff is that swapping for filament/forms, native Livewire form objects, or hand-rolled Blade later becomes a mechanical edit instead of a rewrite. Without the seam, "cheap to try" stops being true the moment you have forty forms depending on it.

Adopt for new forms only. Do not migrate existing working screens. Bound the risk to code you were going to write anyway, so a bad outcome is measured in wasted hours rather than a regression hunt.

Validation layering is non-negotiable. The form class's rules are a UX affordance: inline messages, no full-page round trip. They are never the trust boundary. Anything touching money, permissions, or persisted records keeps a FormRequest (or an explicit $this->validate() on authoritative rules) on the write path. If the form's rules and the FormRequest's rules drift, you have two sources of truth and the weaker one is the one users see.

Standardise Blade rendering once, then reuse it everywhere. This is the highest-leverage part of the package in daily use: one layout grid, one field wrapper that consistently emits label, help text, error message, and aria-describedby/aria-invalid. If the package's helpers don't emit accessibility attributes, wrap them so they do. Retrofitting ARIA across forty screens in month six is a genuinely miserable sprint.

Spike repeaters and conditional fields explicitly, on the second form. Scalar fields are the easy path. Dynamic rows, show/hide driven by other field values, and nested validation keys (items.*.name) are where form abstractions most often diverge from Laravel's expectations. Find that out during the spike, not in month three with a designer waiting on you.

Test the form class, not the markup. Instantiate the form object in a plain unit test and assert rules() output and validation failures directly — that's fast and stable across Livewire versions. Then a smaller number of Livewire feature tests for the round trip (submit → error bag → repopulate). Keep one fixture form that exercises every field type you depend on; that fixture is your upgrade smoke test and the single most valuable artefact of the spike.

Daily loop, once established: add field to the form class → add rule → render through the standard wrapper → assert in the fixture test. If any step of that loop requires touching more than one file, your adapter seam is missing something — fix the seam, not the individual form.

Gotchas and Tips

Bus factor of one is the dominant fact. No issue history, no downstream corpus, no community. Assume the maintainer goes quiet the week after you adopt. The fork isn't paranoia; it's the only mechanism by which you can ship a patch. Budget roughly 5–10% of one engineer's time in year one for fork upkeep, dependency bumps, and internal docs.

Livewire major-version coupling will bite. Livewire 3 → 4 changes routinely break form packages, and with zero dependents you will be the one discovering the breakage — in production. Pin livewire/livewire alongside the package, route both through a dependency PR, and absorb one minor upgrade through your fork before widening adoption.

"Standalone" needs defining before you build the architecture story on it. If it means one schema drives both Livewire components and controller-validated forms, that's a genuine decoupling win. If it only means "usable without the parent NyonCode suite," it's a thinner Filament clone and loses the reason to pay the maintenance cost.

Silent attribute dropping is the accessibility failure mode. Test it directly: pass an unknown prop or aria-* attribute to a field component and confirm it errors or forwards. If it disappears quietly, aria-*, wire:model modifiers, and data-* test hooks can vanish without anyone noticing until an audit.

Error bag naming. Confirm which bag the package writes to. If your layout renders $errors in a specific spot and the package uses a named bag, inline messages will silently not appear and you'll spend an afternoon blaming the validator.

Debugging order when validation "doesn't fire":

  1. Is the form object rebuilt on every Livewire request and losing state? (hydration)
  2. Is the rule string reaching Validator::make intact?
  3. Is the error bag the one Blade reads?

Drop a temporary dd($this->form->rules()) in the submit handler — if rules are empty on the second request, it's hydration, not validation.

Reset and old-input semantics leak. Test the create-after-edit path explicitly. A create form pre-filled with the last edited record is a subtle, embarrassing bug class that most form packages have shipped at least once.

Namespace and asset collisions. Check for clashes with blade-ui-kit and your existing Livewire component registrations. If the package ships views or CSS/JS, namespace or version them so they don't fight your design system on the next upgrade.

Rebuilding the schema on every request costs something. If the form class does real work in fields() (options queries, config lookups), memoize it per request or pass pre-resolved data in. Small forms won't notice; a settings screen with eight relationship-backed selects will.

If Filament is already in the stack, this probably isn't for you. Two layout systems and two validation paths for the same job is a net loss regardless of how pleasant the fluent API is.

Where it fits: internal tools, back-office CRUD, settings screens, MVPs, prototype-heavy phases. Where it doesn't: customer-facing forms that are a differentiator, anything accessibility- or i18n-contractual, payment-adjacent flows, or a roadmap that depends on this layer for years rather than months.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package