fyyyn1210/wire-select

A powerful searchable select box component for Laravel Livewire with database integration

Installs: 4

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 1

pkg:composer/fyyyn1210/wire-select

1.0.1 2025-07-30 07:40 UTC

This package is auto-updated.

Last update: 2025-12-30 08:34:40 UTC


README

🚀 The best and most practical alternative to Select2 for Laravel Livewire - Native searchable select component with database integration, no jQuery dependency!

Complete Installation Tutorial

Quick Start (2 Minutes Setup)

Step 1: Install via Composer

composer require fyyyn1210/wire-select

Step 2: Use in Your Blade Template

<livewire:wire-select-box
    table-name="users"
    field-name="user_id"
    label="Select User" />

That's it! 🎉 Your searchable select is ready!

📋 Detailed Installation Guide

Prerequisites

  • Laravel 10.x or 11.x
  • Livewire 3.x
  • PHP 8.1+

Step-by-Step Installation

1. Install Package

# Via Composer (Recommended)
composer require fyyyn1210/wire-select

# Clear cache after installation
php artisan config:clear
php artisan view:clear

2. Verify Installation

# Check if package is loaded
composer show fyyyn1210/wire-select

3. Publish Configuration (Optional)

# Publish config file for customization
php artisan vendor:publish --provider="Fyyyn1210\WireSelect\WireSelectServiceProvider" --tag="config"

# This creates: config/wire-select.php

4. Publish Views (Optional)

# Publish views for custom styling
php artisan vendor:publish --provider="Fyyyn1210\WireSelect\WireSelectServiceProvider" --tag="views"

# This creates: resources/views/vendor/wire-select/

5. Publish Assets (Optional)

# Publish CSS/JS assets
php artisan vendor:publish --provider="Fyyyn1210\WireSelect\WireSelectServiceProvider" --tag="assets"

# This creates: public/vendor/wire-select/

🎯 Usage Examples

Example 1: Basic Database Search

Create Migration (if needed)

// database/migrations/create_users_table.php
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email');
    $table->timestamps();
});

Seed Data (if needed)

// database/seeders/UserSeeder.php
User::factory()->count(50)->create();

Use in Livewire Component

// app/Livewire/UserForm.php
<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\Attributes\On;

class UserForm extends Component
{
    public $user_id;
    public $formData = [];

    #[On('selectionChanged')]
    public function handleUserSelection($data)
    {
        if ($data['field'] === 'user_id') {
            $this->user_id = $data['value'];
        }
    }

    public function save()
    {
        $this->validate([
            'user_id' => 'required|exists:users,id'
        ]);

        // Save logic here
    }

    public function render()
    {
        return view('livewire.user-form');
    }
}

Blade Template

<!-- resources/views/livewire/user-form.blade.php -->
<div>
    <form wire:submit="save">
        <livewire:wire-select-box
            table-name="users"
            search-column="name"
            key-column="id"
            value-column="name"
            field-name="user_id"
            label="Select User"
            placeholder="Type to search users..."
            :required="true" />

        @error('user_id')
            <span class="text-danger">{{ $message }}</span>
        @enderror

        <button type="submit" class="btn btn-primary">Save</button>
    </form>

    @if($user_id)
        <div class="alert alert-success">
            Selected User ID: {{ $user_id }}
        </div>
    @endif
</div>

Example 2: Static Array Data

// app/Livewire/CategoryForm.php
<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\Attributes\On;

class CategoryForm extends Component
{
    public $categories = [
        1 => 'Technology',
        2 => 'Business',
        3 => 'Science',
        4 => 'Health',
        5 => 'Education'
    ];

    public $selected_category;

    #[On('selectionChanged')]
    public function handleSelection($data)
    {
        if ($data['field'] === 'category') {
            $this->selected_category = $data['value'];
        }
    }

    public function render()
    {
        return view('livewire.category-form');
    }
}
<!-- resources/views/livewire/category-form.blade.php -->
<div>
    <livewire:wire-select-box
        :items="$categories"
        field-name="category"
        label="Select Category"
        placeholder="Search categories..."
        icon="ki-category"
        :selected-value="$selected_category" />
</div>

Example 3: Advanced Database with Conditions

// app/Livewire/ProductForm.php
<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\Attributes\On;

class ProductForm extends Component
{
    public $product_id;
    public $category_id = 1; // Pre-selected category

    #[On('selectionChanged')]
    public function handleProductSelection($data)
    {
        if ($data['field'] === 'product_id') {
            $this->product_id = $data['value'];
        }
    }

    public function render()
    {
        return view('livewire.product-form');
    }
}
<!-- resources/views/livewire/product-form.blade.php -->
<div>
    <livewire:wire-select-box
        table-name="products"
        search-column="name"
        key-column="id"
        value-column="name"
        field-name="product_id"
        label="Select Active Product"
        :condition="['status' => 'active', 'category_id' => $category_id]"
        placeholder="Search products..."
        icon="ki-box"
        :limit="20"
        max-height="300px" />
</div>

🔧 Configuration Options

Config File (config/wire-select.php)

<?php

return [
    'defaults' => [
        'placeholder' => 'Search...',
        'empty_message' => 'No data found',
        'max_height' => '250px',
        'limit' => 10,
        'icon' => 'ki-search',
        'icon_path' => 2,
        'required' => true,
    ],

    'css' => [
        'container' => 'mb-3',
        'label' => 'form-label fw-semibold',
        'input' => 'form-control',
        'dropdown' => 'border rounded shadow-sm',
    ]
];

All Available Props

<livewire:wire-select-box
    {{-- Data Source --}}
    :items="$array_data"              <!-- Static array data -->
    table-name="table_name"           <!-- Database table -->
    search-column="column_name"       <!-- Column to search -->
    key-column="id"                   <!-- Key column -->
    value-column="name"               <!-- Display column -->
    :condition="['status' => 'active']" <!-- WHERE conditions -->

    {{-- Behavior --}}
    field-name="field_name"           <!-- Field identifier -->
    :selected-value="$value"          <!-- Pre-selected value -->
    :limit="20"                       <!-- Max results -->
    :show-init="true"                 <!-- Show initial data -->

    {{-- Appearance --}}
    label="Select Item"               <!-- Label text -->
    placeholder="Search..."           <!-- Placeholder text -->
    icon="ki-search"                  <!-- Icon class -->
    :icon-path="2"                    <!-- Icon paths count -->
    max-height="300px"                <!-- Max dropdown height -->
    empty-message="No data found"     <!-- Empty state message -->

    {{-- States --}}
    :required="true"                  <!-- Required field -->
    :disabled="false"                 <!-- Disabled state -->
/>

🚀 Migration from Select2

Before (Select2 Code)

<!-- Old Select2 HTML -->
<div class="form-group">
    <label>Select User</label>
    <select id="user-select" class="form-control select2" data-placeholder="Choose user...">
        <option value=""></option>
    </select>
</div>

<script>
$(document).ready(function() {
    $('#user-select').select2({
        ajax: {
            url: '{{ route("users.search") }}',
            dataType: 'json',
            delay: 250,
            data: function (params) {
                return {
                    q: params.term,
                    page: params.page
                };
            },
            processResults: function (data, params) {
                params.page = params.page || 1;
                return {
                    results: data.items,
                    pagination: {
                        more: (params.page * 30) < data.total_count
                    }
                };
            },
            cache: true
        },
        placeholder: 'Search for users',
        minimumInputLength: 1,
        templateResult: formatUser,
        templateSelection: formatUserSelection
    });

    $('#user-select').on('select2:select', function (e) {
        var data = e.params.data;
        @this.set('user_id', data.id);
    });
});

function formatUser (user) {
    if (user.loading) {
        return user.text;
    }
    return $('<span>' + user.name + ' (' + user.email + ')</span>');
}

function formatUserSelection (user) {
    return user.name || user.text;
}
</script>
// Old API Route
Route::get('/users/search', function (Request $request) {
    $users = User::where('name', 'like', '%' . $request->q . '%')
                 ->orWhere('email', 'like', '%' . $request->q . '%')
                 ->paginate(30);

    return response()->json([
        'items' => $users->items(),
        'total_count' => $users->total()
    ]);
});

After (Livewire Searchable Select)

<!-- New Livewire Component - ONE LINE! -->
<livewire:wire-select-box
    table-name="users"
    search-column="name"
    field-name="user_id"
    label="Select User"
    placeholder="Search for users..." />
// Handle selection in your Livewire component
#[On('selectionChanged')]
public function handleUserSelection($data)
{
    if ($data['field'] === 'user_id') {
        $this->user_id = $data['value'];
    }
}

Lines of code reduced: 60+ → 2 lines!

🛠️ Troubleshooting

Common Issues

Issue 1: Component Not Found

# Error: Component [wire-select-box] not found
# Solution: Clear cache
php artisan config:clear
php artisan view:clear
composer dump-autoload

Issue 2: Styles Not Applied

# Make sure Bootstrap/your CSS framework is loaded
# Or publish and customize the views
php artisan vendor:publish --provider="Fyyyn1210\WireSelect\WireSelectServiceProvider" --tag="views"

Issue 3: Database Connection Issues

// Make sure your database table exists and has the specified columns
// Check your .env database configuration
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

Issue 4: Events Not Working

// Make sure you're using the correct event listener
use Livewire\Attributes\On;

#[On('selectionChanged')]
public function handleSelection($data)
{
    // Your logic here
}

Debug Mode

<!-- Add debug info to see what's happening -->
<livewire:wire-select-box
    table-name="users"
    field-name="user_id"
    label="Select User" />

<!-- Debug output -->
@if(config('app.debug'))
    <div class="mt-2 small text-muted">
        Selected: {{ $user_id ?? 'None' }}
    </div>
@endif

🎉 You're Ready!

Your Livewire Searchable Select is now installed and ready to use. Start with a simple example and gradually explore more advanced features.

Need help? Check our GitHub Issues or Discussions.