ringlesoft/laravel-selectable
Generate HTML tags from Laravel collections with a simple, flexible API. Choose label/value fields (strings or closures), set selected/disabled items, add classes/data attributes, group options, and export selectable arrays for AJAX/SPAs.
Installation: Add the package via Composer:
composer require ringlesoft/laravel-selectable
No additional configuration is required.
First Use Case: Convert a Laravel collection to select options in a Blade template:
<select name="user_id">
{!! \App\Models\User::all()->toSelectOptions() !!}
</select>
This uses id as the value and name as the label by default.
Quick Customization: Override defaults with inline parameters:
<select name="user_id">
{!! \App\Models\User::all()->toSelectOptions('email', 'uuid', '6490132934f22') !!}
</select>
Here, email is the label, uuid is the value, and '6490132934f22' is the selected option.
v1.0.4+ for IDE helper improvements and bug fixes.Selectable class methods in src/Selectable.php for extension points.Basic Select Generation
Use toSelectOptions() for simple dropdowns:
{!! $users->toSelectOptions() !!}
User::query()->get()->toSelectOptions()).Fluent Builder Pattern Chain methods for complex selects:
{!! $users
->toSelectable()
->withLabel(fn($user) => "{$user->first_name} {$user->last_name}")
->withSelected($currentUser->id)
->withDisabled(fn($user) => $user->is_inactive)
->toSelectOptions()
!!}
API/SPA Integration Convert to an array for frontend consumption:
$selectItems = User::all()->toSelectable()->toSelectItems();
[
{ "label": "John Doe", "value": "1", "selected": true, "dataAttributes": { "hidden": false } }
]
Grouped Options
Leverage Laravel’s groupBy:
{!! User::all()
->groupBy(fn($user) => $user->department)
->toSelectable()
->toSelectOptions()
!!}
<optgroup> elements automatically.toSelectItems() to validate selected values:
$request->validate(['user_ids' => 'required|array']);
$selectedIds = $request->input('user_ids');
->withDataAttribute('user-role', fn($user) => $user->role)
collect(['First', 'Second'])->toSelectOptions();
collect([['name' => 'First', 'id' => 1]])->toSelectable()->withValue('id')->toSelectOptions();
Blade Template Queries
User::all()->toSelectOptions()). Use a service layer or controller method instead.public function edit(User $user) {
return view('edit', ['users' => User::all()]);
}
Closure Performance
withLabel(fn($item) => ...)) can slow rendering.Selected/Disabled Logic
withSelected/withDisabled are evaluated per item, which may not scale for complex logic.$users->whereNotIn('id', [1, 2])->toSelectable()->withDisabled(fn($user) => $user->is_banned)
IDE Autocompletion
toSelectable() methods.v1.0.2+):
composer require --dev ringlesoft/laravel-selectable-ide-helper
toSelectItems() to debug the array structure before rendering:
dd(User::all()->toSelectable()->toSelectItems());
value fields are unique; duplicates may cause rendering issues.data-*, class) are applied correctly.Custom Selectable Builder
Extend the Selectable class to add domain-specific methods:
class CustomSelectable extends \Ringlesoft\Selectable\Selectable {
public function withCustomAttribute(string $name, $value) {
return $this->withDataAttribute($name, $value);
}
}
withPriority()).Override Defaults Globally Use a macro to modify default behavior:
\Ringlesoft\Selectable\Selectable::macro('withDefaultClasses', function() {
return $this->withClass('select-option');
});
Non-Laravel Collections
Support arrays or custom objects by implementing Arrayable:
collect([1, 2, 3])->toSelectable()->withValue(fn($item) => "item_$item");
<select multiple>, ensure your frontend handles array submissions (e.g., user_ids[]).toSelectOptions() renders an empty <select>; add a placeholder if needed:
<select name="user_id">
<option value="" disabled selected>Select a user</option>
{!! $users->toSelectOptions() !!}
</select>
How can I help you explore Laravel packages today?