Weave Code
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

Nova Multiselect Field Laravel Package

outl1ne/nova-multiselect-field

View on GitHub
Deep Wiki
Context7
## 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.

  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',
                ]),
        ];
    }
    
  2. Database Column: Use string, text, or varchar for the column (values are stored as JSON arrays by default).


First Use Case: Simple Multi-Select

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

Implementation Patterns

1. Static vs. Dynamic Options

  • Static Options: Use ->options([]) for predefined choices (e.g., fixed categories).
  • Dynamic Options: Use ->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
    

2. Relationship Handling

  • BelongsToMany: Sync with pivot tables:
    Multiselect::make('Tags', 'tags')
        ->belongsToMany(\App\Nova\Tag::class);
    
  • BelongsTo: Use for single-selection relationships (e.g., country → state):
    Multiselect::make('State')
        ->belongsTo(\App\Nova\State::class)
        ->singleSelect();
    

3. Conditional Logic

  • Dependencies: Chain selects dynamically:
    // Country → Language
    Multiselect::make('Country')
        ->options(['IT' => 'Italy', 'SG' => 'Singapore']);
    
    Multiselect::make('Language')
        ->optionsDependOn('Country', [
            'IT' => ['it' => 'Italian'],
            'SG' => ['en' => 'English', 'ms' => 'Malay'],
        ]);
    
  • Distinct Values: Prevent duplicate selections across fields:
    Multiselect::make('Primary Tags')
        ->distinct('tag_group');
    
    Multiselect::make('Secondary Tags')
        ->distinct('tag_group'); // Shares options with Primary Tags
    

4. UI/UX Customization

  • Reordering: Enable drag-and-drop for ordered lists:
    Multiselect::make('Priorities')
        ->reorderable()
        ->saveAsJSON(); // Store as JSON array for ordered data
    
  • Tags: Allow free-form input:
    Multiselect::make('Custom Tags')
        ->taggable()
        ->placeholder('Add tags...');
    
  • Grouping: Organize options hierarchically:
    ->options([
        ['label' => 'Small', 'group' => 'Men Sizes', 'value' => 'MS'],
        ['label' => 'Medium', 'group' => 'Men Sizes', 'value' => 'MM'],
    ]);
    

5. Index View Optimization

  • Limit displayed values to avoid clutter:
    Multiselect::make('Selected Items')
        ->indexValueDisplayLimit(5) // Show max 5 items
        ->indexCharDisplayLimit(20); // Truncate long labels
    

Gotchas and Tips

Common Pitfalls

  1. Database Storage:

    • Values are stored as JSON strings by default (e.g., "["admin","editor"]").
    • Use ->saveAsJSON() if your column is JSON type to store raw arrays.
    • Gotcha: Forgetting ->saveAsJSON() may cause serialization issues with complex data.
  2. Async Performance:

    • Set ->optionsLimit() to avoid overwhelming the UI with too many options.
    • Tip: Use ->belongsToMany(..., false) to load options eagerly (not recommended for large datasets).
  3. Dependencies:

    • The dependent field’s optionsDependOn key must match the parent field’s option key.
    • Gotcha: Async dependencies may cause delays if not configured properly.
  4. Taggable Fields:

    • Dynamically added tags are not persisted by default. Ensure your model handles custom values.
    • Tip: Use ->taggable() sparingly—validate custom inputs server-side.
  5. Reordering:

    • Requires ->saveAsJSON() to preserve order in the database.
    • Gotcha: The reorder button may appear incorrectly if ->singleSelect() is used (fixed in v5.0.1).
  6. Distinct Groups:

    • Fields in the same distinct() group share option exclusivity.
    • Tip: Use descriptive group names (e.g., ->distinct('user_roles')).

Debugging Tips

  1. Check API Responses:

    • For async fields, verify the endpoint returns {"id": "value"} format.
    • Use browser dev tools to inspect network requests.
  2. Storage Validation:

    • If values appear corrupted, check if the column type matches the stored data (e.g., text vs. JSON).
  3. Vue Component Overrides:

    • Clear browser cache after registering custom components (e.g., NovaMultiselectDetailFieldValue).
    • Tip: Test overrides in isolation by temporarily disabling other Nova packages.
  4. Localization:

    • Publish translations with:
      php artisan vendor:publish --provider="Outl1ne\MultiselectField\FieldServiceProvider" --tag="translations"
      
    • Gotcha: Forgetting to publish may leave UI strings in English.

Extension Points

  1. Custom Components:

    • Override the detail view or tag template via Vue components (see README).
    • Example: Add icons or badges to selected tags.
  2. Validation:

    • Add Laravel validation rules to the resource’s rules() method:
      public static $rules = [
          'football_teams' => 'required|array|max:3',
      ];
      
  3. Nova 5 Features:

    • Leverage repeater fields integration (v5.1.2+) for nested multiselects:
      Repeater::make('Items')
          ->fields([
              Multiselect::make('Categories')
                  ->belongsToMany(\App\Nova\Category::class),
          ]);
      
  4. Select All:

    • Enable bulk selection with ->showSelectAll() (v5.1.1+):
      Multiselect::make('Bulk Actions')
          ->options(['edit' => 'Edit', 'delete' => 'Delete'])
          ->showSelectAll();
      

Pro Tips

  • Performance: For large datasets, combine ->asyncResource() with ->optionsLimit() and lazy-loading.
  • Accessibility: Use ->placeholder() and clear labels to improve usability.
  • Testing: Test edge cases like:
    • Rapid selections/deselections.
    • Concurrent edits (e.g., two users selecting the same option).
    • Database migrations (ensure JSON columns are compatible).
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky