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

jackbayliss/livewire-select2

A Laravel Livewire component that integrates Select2 for searchable, AJAX-powered dropdowns, with server-side pagination, filtering, and simple Blade usage for dynamic select inputs.

View on GitHub
Deep Wiki
Context7

Getting Started

jackbayliss/livewire-select2 is a thin wrapper that lets you use Select2 (search, tags, multi-select, remote data) on a Livewire-bound <select> without hand-writing the jQuery init/teardown glue. It is a UI convenience package, not a form or state package — Livewire still owns the value, Select2 owns the widget.

composer require jackbayliss/livewire-select2

Where to look first: the README's first example block is the whole integration surface. The package exposes a single component (a Blade-style tag plus a wire:model bind) and a small config file for default options. Publish the config only if you need to change global defaults:

php artisan vendor:publish --tag=livewire-select2-config

First use case — replace a plain select in an existing form with a searchable one and change nothing else in your component:

<livewire:select2
    name="user_id"
    wire:model="userId"
    :options="$this->users"   {{-- ['1' => 'Alice', '2' => 'Bob'] or a collection --}}
    placeholder="Search users…"
/>

Because it is still a normal form input under the hood, validation, wire:model defer/live behaviour, and $this->validate() in your Livewire component all keep working unchanged. That is the main reason to reach for this over a bespoke Alpine combobox — it does not change your server-side contract.

Version note (1.3): this release only widens the framework constraint to include Laravel 13. There are no API changes; the upgrade is safe. If you pin jackbayliss/livewire-select2 in composer.json, a composer update on a Laravel 12 app will not pull anything unexpected — but check the resolved illuminate/support constraint if you are on an older LTS (9/10), where you may need to stay on 1.2.

Implementation Patterns

Static option lists. Pass an associative array or collection; keys are submitted, values are displayed. Resolve options in a computed property (#[Computed]) so they are not re-queried on every render of a large form.

Remote/AJAX search. For large tables, do not hydrate thousands of options into the DOM. Feed Select2 an endpoint (a lightweight invokable controller or a dedicated Livewire method) that returns ['results' => [['id' => .., 'text' => ..]]], and pass the currently selected label in separately so the widget renders correctly before the first search. Keep the query scoped and paginated (->limit(20)) — Select2 fires on every keystroke.

Dependent selects (country → city). Listen for the parent's change in your Livewire component (updatedCountryId()), rebuild the child's option array, and dispatch a refresh event so the JS widget re-reads the options after the DOM morph:

public function updatedCountryId(): void
{
    $this->cityId = null;
    $this->dispatch('select2-refresh');
}

Multi-select / tags. A multiple select posts an array; type the Livewire property as array and validate with array + exists rules. For many-to-many (sync()), the array is exactly what you want — no mapping layer needed.

In modals and dynamically rendered forms. Because the widget is JS-initialised, anything that mounts markup after page load (a modal, a @if($showForm) block) needs the component to re-init. Prefer rendering the component inside the conditional rather than toggling display:none, and emit the refresh event from the action that opens the modal.

Integration tip: wrap the component in a small Blade partial of your own (<x-form.select2 ... />) that forwards name, wire:model, multiple, and placeholder. It gives you one place to add labelling/error markup (@error('user_id')) and keeps Select2-specific attributes out of your feature views.

Gotchas and Tips

  • jQuery dependency. Select2 is a jQuery plugin. The package brings its own JS, but if your app has removed jQuery or loads it late, init will silently no-op. Symptoms: a plain select with no search box, no console error. Check the network tab for the Select2 script and confirm window.jQuery exists before your app bundle runs.
  • wire:navigate / SPA navigation. Full-page-navigated apps are fine; with wire:navigate the jQuery plugin state survives in a way the DOM no longer matches. Re-init on livewire:navigated (or disable wire:navigate for the page). This is the single most common "it works once then breaks" report.
  • Morphing eats the widget. Any Livewire re-render that touches the component's parent can strip Select2's generated markup. Bind with wire:model (not wire:model.live on every keystroke of an unrelated field), and keep the component's own attributes stable so Livewire can skip it.
  • Key type mismatch. Select2 compares option values as strings. If your property is typed int and you pre-select with :value="123", the label may not appear until you interact. Cast consistently ((string) $id) or use ->mapWithKeys(fn ($m) => [(string) $m->id => $m->name]).
  • Multiple + empty state. A cleared multi-select sends [], which Livewire may coerce to null depending on your property default. Normalise in updated* hooks before validating, or your array rule will fail on empty submits.
  • Styling is your problem. The package does not ship a theme. Select2's default CSS will clash with Tailwind/Bootstrap 5 forms; budget an hour for .select2-container--default overrides, and use the container class attribute to scope them.
  • Debugging order: (1) is the underlying <select> in the DOM with the right options, (2) did Select2 initialise (look for .select2-container), (3) does the hidden input update on change, (4) does the Livewire property update on the network payload. That sequence isolates JS vs. binding vs. server in four steps.
  • Extension point: the package's config is the intended seam for defaults (placeholder, allowClear, theme). Everything beyond that is Select2's own options API — pass them through as an array rather than patching the package, so future Laravel-constraint releases (like 1.3) stay zero-effort upgrades.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console