outl1ne/nova-multiselect-field
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require outl1ne/nova-multiselect-field
Ensure your Nova version is ^5.0 and PHP is ^8.1.
Basic Usage:
Add the field to your Nova resource like a native Select field, but with JSON storage:
use Outl1ne\MultiselectField\Multiselect;
public function fields(Request $request)
{
return [
Multiselect::make('Football Teams')
->options([
'liverpool' => 'Liverpool FC',
'tottenham' => 'Tottenham Hotspur',
]),
];
}
Database Column:
Use string, text, or varchar for the column (values are stored as JSON arrays by default).
Replace a native Select field with a searchable, multi-select dropdown for categories, tags, or roles. Example:
Multiselect::make('User Roles')
->options([
'admin' => 'Administrator',
'editor' => 'Editor',
'viewer' => 'Viewer',
])
->placeholder('Assign roles...')
->max(3); // Limit to 3 selections
->options([]) for predefined choices (e.g., fixed categories).->asyncResource(Model::class) or ->api('/endpoint', Model::class) for database-backed options (e.g., users, products).
// Async from a Nova Resource
Multiselect::make('Categories')
->asyncResource(\App\Nova\Category::class)
->optionsLimit(20); // Optimize performance
Multiselect::make('Tags', 'tags')
->belongsToMany(\App\Nova\Tag::class);
Multiselect::make('State')
->belongsTo(\App\Nova\State::class)
->singleSelect();
// Country → Language
Multiselect::make('Country')
->options(['IT' => 'Italy', 'SG' => 'Singapore']);
Multiselect::make('Language')
->optionsDependOn('Country', [
'IT' => ['it' => 'Italian'],
'SG' => ['en' => 'English', 'ms' => 'Malay'],
]);
Multiselect::make('Primary Tags')
->distinct('tag_group');
Multiselect::make('Secondary Tags')
->distinct('tag_group'); // Shares options with Primary Tags
Multiselect::make('Priorities')
->reorderable()
->saveAsJSON(); // Store as JSON array for ordered data
Multiselect::make('Custom Tags')
->taggable()
->placeholder('Add tags...');
->options([
['label' => 'Small', 'group' => 'Men Sizes', 'value' => 'MS'],
['label' => 'Medium', 'group' => 'Men Sizes', 'value' => 'MM'],
]);
Multiselect::make('Selected Items')
->indexValueDisplayLimit(5) // Show max 5 items
->indexCharDisplayLimit(20); // Truncate long labels
Database Storage:
"["admin","editor"]").->saveAsJSON() if your column is JSON type to store raw arrays.->saveAsJSON() may cause serialization issues with complex data.Async Performance:
->optionsLimit() to avoid overwhelming the UI with too many options.->belongsToMany(..., false) to load options eagerly (not recommended for large datasets).Dependencies:
optionsDependOn key must match the parent field’s option key.Taggable Fields:
->taggable() sparingly—validate custom inputs server-side.Reordering:
->saveAsJSON() to preserve order in the database.->singleSelect() is used (fixed in v5.0.1).Distinct Groups:
distinct() group share option exclusivity.->distinct('user_roles')).Check API Responses:
{"id": "value"} format.Storage Validation:
text vs. JSON).Vue Component Overrides:
NovaMultiselectDetailFieldValue).Localization:
php artisan vendor:publish --provider="Outl1ne\MultiselectField\FieldServiceProvider" --tag="translations"
Custom Components:
Validation:
rules() method:
public static $rules = [
'football_teams' => 'required|array|max:3',
];
Nova 5 Features:
Repeater::make('Items')
->fields([
Multiselect::make('Categories')
->belongsToMany(\App\Nova\Category::class),
]);
Select All:
->showSelectAll() (v5.1.1+):
Multiselect::make('Bulk Actions')
->options(['edit' => 'Edit', 'delete' => 'Delete'])
->showSelectAll();
->asyncResource() with ->optionsLimit() and lazy-loading.->placeholder() and clear labels to improve usability.How can I help you explore Laravel packages today?