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 Fields Laravel Package

robinthijsen/livewire-fields

A Laravel Livewire package offering reusable, configurable form field components. Build and render inputs, selects, and related fields quickly, keeping forms consistent across your app with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Because this package has a small surface area and thin documentation, budget your first hour for reading the source rather than the README. That time pays back immediately — the whole package is a handful of Blade views plus a couple of component classes, and guessing at prop names is slower than grepping.

Install and confirm the 1.0.3 baseline.

composer require robinthijsen/livewire-fields:^1.0.3

Pin ^1.0.3 rather than ^1.0. The 1.0.3 release is explicitly "Fix Checkbox and Select component", which means 1.0.0–1.0.2 render those two controls incorrectly in at least one scenario. There is no reason to allow a resolve onto a known-broken tag.

Then:

php artisan vendor:publish --tag=livewire-fields-views   # only if you must change markup
php artisan view:clear

Skip the view publish on day one. Published views shadow every future package fix — that is the most common reason an upgrade "does nothing".

Where to look first, in order.

  1. src/View/Components/ — the component classes. This is where the prop list, defaults, and any attribute-forwarding logic actually live. It is the source of truth; treat the README as a hint.
  2. resources/views/components/ — the Blade markup. Read the Checkbox and Select templates specifically, since those are what 1.0.3 changed. You need to know whether wire:model and other attributes are forwarded via $attributes or dropped.
  3. config/livewire-fields.php (if present) — default classes, wrapper elements, error display behaviour.
  4. composer.json — the Livewire major version constraint. Confirm your app is inside it before you build anything on top.

First use case. Take one existing form and convert a single text field and a single select. Do not convert the whole form yet.

<form wire:submit="save">
    <x-livewire-fields::text name="email" wire:model.blur="email" label="Email" />

    <x-livewire-fields::select
        name="country"
        wire:model="country"
        :options="$countries"
        placeholder="Choose…"
        label="Country"
    />

    <button type="submit">Save</button>
</form>

Note the namespace prefix — confirm the actual tag name from the component registration, not from memory. Then verify three things before going further:

  • Typing in the field updates the Livewire property (open the network tab or add wire:model.live temporarily and watch for round-trips).
  • A validation failure re-renders with the error message inline and the previously entered value still in the input.
  • The select pre-selects the right option after that failed submit.

That last one is the exact path 1.0.3 touched. If it fails, stop and diff the component source before building on it.

Implementation Patterns

Adopt per-form, not per-page. Convert every field in one form at a time and leave neighbouring forms alone until that form is verified. Mixed native and component inputs inside the same form diverge in error styling and spacing, and the inconsistency reads as a bug to users.

Rely on wire:model on the component tag, but verify forwarding once. The package's selling point is that wire:model works without extra wiring. Confirm empirically that the attribute reaches the underlying <input>/<select> element in the rendered HTML — wire:model, wire:model.live, wire:model.blur, and wire:model.defer all need to survive. If the component swallows modifiers, your only options are native inputs or a wrapper that re-applies them.

Bind modals and forms the same way. The Livewire property is the single source of truth; never mix old() into a Livewire-bound input. old() only matters if you render the same form outside Livewire.

Normalise options before they reach the component. Do the mapping in the Livewire component's mount() or a computed property, not in the Blade file:

public array $countries = [];

public function mount(): void
{
    $this->countries = Country::orderBy('name')->pluck('name', 'iso')->all();
}

Passing a raw Eloquent collection to :options typically produces an empty select or an array-to-string warning. Pluck to a flat key => label array and the semantics stay explicit.

Checkbox groups need array properties and array rules. For multi-value fields:

<x-livewire-fields::checkbox name="roles[]" wire:model="roles" value="admin" label="Admin" />
#[Validate('array')]
public array $roles = [];

The single most common breakout point is the checked state of a group surviving a failed validation — verify that all previously ticked boxes come back, not just the first.

Wrap the package in your own components. One thin layer buys you a cheap upgrade path:

{{-- resources/views/components/forms/select.blade.php --}}
<x-livewire-fields::select
    {{ $attributes->merge(['class' => 'w-full rounded-md border-gray-300']) }}
    :options="$options"
    :selected="$selected ?? null"
/>

If a future release renames a prop, you edit one file instead of every view. This also gives you a place to enforce your design tokens rather than repeating Tailwind strings.

Test at the Livewire level, not the HTML level. The natural assertion is on component state, but markup matters here because rendering is what 1.0.3 fixed:

Livewire::test(RegistrationForm::class)
    ->set('country', 'nl')
    ->call('save')
    ->assertHasErrors(['email' => 'required'])
    ->assertSee('value="nl" selected', false);

Add one regression test per control fixed in 1.0.3 — a checkbox that round-trips its checked state and a select that round-trips its selected option after a validation failure. Those two tests are your tripwire for the next patch release.

Build a render-snapshot fixture set. Capture the HTML for a representative sample: checked and unchecked checkbox, single select, select with placeholder, select with old()-style pre-selection, disabled variants, and a field with a validation error. Any future bump gets diffed against this in five minutes. It is the single highest-value artifact you can build around this package.

Gotchas and Tips

  • Unchecked checkboxes submit nothing. When the box is unticked the key is absent from the request and the Livewire payload. Use $request->boolean('terms'), a sometimes|accepted rule, or a #[Validate('accepted')] attribute on a bool property — required alone behaves surprisingly if a hidden fallback input is also rendered. Check the component source to see whether it emits one.
  • Published views silently defeat upgrades. If you published views in the past to tweak markup, those local copies do not receive the 1.0.3 Checkbox/Select fix. Re-publish or diff your copies against the package originals after every bump. Same applies to any CSS or JS you published and hand-edited.
  • The 1.0.3 fix implies earlier releases render those components wrong. After composer update, always php artisan view:clear and rebuild assets. Stale compiled Blade views will make the fix appear not to have landed.
  • Attribute precedence is easy to misread. With {{ $attributes->merge([...]) }}, call-site attributes win over merged ones — but a literal attribute hardcoded inside the component template beats everything. If your class, disabled, or wire:model has no effect, grep the component source for a hardcoded version before blaming the package or Livewire.
  • Numeric option keys get cast to integers. PHP turns "0" and "1" array keys into int. If a select's pre-selection silently no-ops for a status code or numeric ID, this is usually why — the selected comparison fails on type. Stringify keys before passing them, or confirm the component uses loose comparison.
  • Placeholder semantics matter with required. Check whether the placeholder renders value="" and whether it is disabled. A disabled empty option plus a required rule produces a validation message the user cannot clear if they never open the select — they have to open it and pick something, which is fine, but the error copy won't tell them that.
  • Nested field names drift between binding and validation. wire:model="preferences.newsletter" needs the validation rule key preferences.newsletter and the checkbox name="preferences[newsletter]". Any mismatch means remembered state is empty after a failed submit. Use Livewire's dot notation consistently and set the HTML name to the bracketed form only where you genuinely need a form post.
  • Custom error bags and nested errors. Components typically assume the default bag and a flat name. If you use $errors->{bag} or names like items.0.qty, expect to wire error display manually or override the view.
  • Tailwind purging. If the package ships default class strings that appear in Blade files inside vendor/, Tailwind's content scanner may not see them. Add the package's view path to tailwind.config.js content if default styling looks half-applied in production but fine locally.
  • Livewire major version compatibility. The package is explicitly Livewire-oriented, so a Livewire 3 → 4 style jump is a real compatibility question. Check composer.json constraints before planning a Livewire upgrade; this package may become the blocker.
  • Config caching in deploy. If defaults live in a published config file, php artisan config:cache freezes them. Clear config cache in CI before running tests that assert on default classes.
  • Extension points, in order of preference: config file → your own wrapper component → sub-classing the component class and re-registering the alias → publishing and overriding the Blade view. Work left to right. Reserving published views as a last resort keeps every future patch cheap.
  • Debugging a rendering problem: dd() inside the component's render() or dump $attributes in the Blade file. That reveals in one step whether the problem is a dropped attribute, a hardcoded literal, or a prop default you didn't know existed.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect