๐ฏ New Features
Collection Names Support
-
Multi-Picker Support - Added collection name support for multiple pickers on the same page
- New
collection_name
column inmedia_has_models
pivot table - Use
->collection('name')
method to specify collection for each picker - Each picker maintains its own separate media attachments
- Collection filtering in all trait methods
- Backward compatible (null collection name supported)
- New
-
Migration:
2024_10_21_000000_add_collection_name_to_media_has_models_table.php
- Added
collection_name
(nullable string) column - Added
responsive_images
(boolean, default false) column - Supports rollback with proper column cleanup
- Added
-
Updated Methods with Collection Support:
// Define separate collections for different pickers Forms\Components\MediaManagerPicker::make('featured_image') ->collection('featured') ->single(); Forms\Components\MediaManagerPicker::make('gallery_images') ->collection('gallery') ->multiple(); // Retrieve media by collection $product->getMediaManagerMedia('featured'); $product->getMediaManagerMedia('gallery'); $product->getMediaManagerUrl('featured'); $product->getMediaManagerUrls('gallery');
Responsive Images Support
-
Spatie Media Library Integration - Added responsive images support using Spatie's built-in functionality
- New
->responsiveImages()
method on MediaManagerPicker - Automatic responsive image generation when enabled
- Responsive images flag stored in pivot table
- Multiple methods to retrieve responsive image URLs and srcset
- New
-
New Trait Methods for Responsive Images:
getMediaManagerResponsiveImages(?string $collectionName = null)
- Get media with responsive image datagetMediaManagerSrcset(?string $collectionName = null)
- Get srcset attribute for first mediagetMediaManagerSrcsets(?string $collectionName = null)
- Get all srcset attributesgetMediaManagerResponsiveUrls(?string $collectionName = null)
- Get responsive URLs for first mediagetAllMediaManagerResponsiveUrls(?string $collectionName = null)
- Get all responsive URLs
-
Usage Example:
// Enable responsive images Forms\Components\MediaManagerPicker::make('hero_image') ->collection('hero') ->single() ->responsiveImages(); // In Blade templates <img src="{{ $model->getMediaManagerUrl('hero') }}" srcset="{{ $model->getMediaManagerSrcset('hero') }}" alt="Hero Image"> // Get detailed responsive data $responsiveImages = $model->getMediaManagerResponsiveImages('gallery'); // Returns: ['media' => $media, 'url' => $url, 'responsive_urls' => [...], 'srcset' => '...']
Media Ordering & Reordering
-
Drag & Drop Reordering - Added drag and drop functionality to reorder media items in MediaManagerPicker
- Visual drag handle (three bars icon) appears when multiple items are selected
- Smooth animation during drag (150ms)
- Ghost effect while dragging (40% opacity)
- Cursor changes to "grab" on hover over drag handle
- Only displays for multiple selection mode with 2+ items
- Proper cleanup and reinitialization of Sortable instances
-
Order Column Support - Added
order_column
tomedia_has_models
pivot table- New migration:
2024_10_20_000000_add_order_column_to_media_has_models_table.php
- Unsigned integer column with index for performance
- Nullable to support backward compatibility
- Automatically managed during attach/sync operations
- New migration:
-
Order Persistence
- Media items maintain their order across save/load operations
- Order preserved when using
attachMediaManagerMedia()
- Order preserved when using
syncMediaManagerMedia()
- Order reflected in all
getMediaManagerMedia()
calls - Order properly hydrated when editing existing records
๐ง Bug Fixes
MediaManagerPicker Selection Issues
-
Fixed: Media selection not being set to form - Resolved inconsistent event detail structure
- Changed from direct data to wrapped structure:
{ media: ... }
- Ensures reliable state updates across all scenarios
- Handles both single and multiple selection modes
- Fixed race conditions with
isProcessing
flag
- Changed from direct data to wrapped structure:
-
Fixed: Reordering persistence - Completely rewrote view logic for reliable drag & drop
- Server-side ordering now respects state array order
- Alpine.js state properly synced with Livewire
- Added
wire:key
for proper Livewire DOM tracking - State watcher reinitializes Sortable after re-renders
- Prevents order from reverting after drag operations
InteractsWithMediaManager Trait Updates
-
Collection Name Parameter - Changed
getMediaManagerUrl()
andgetMediaManagerUrls()
methods- Previously: Accepted
$conversion
parameter for image transformations - Now: Accepts
$collectionName
parameter to filter by media collection - More useful for retrieving specific media groups (e.g., 'gallery', 'thumbnails', 'documents')
- Breaking change from previous implementation
- Previously: Accepted
-
Updated Methods with Ordering:
// Now returns media in order $product->getMediaManagerMedia('gallery'); $product->getMediaManagerUrl('thumbnails'); // Get first from thumbnails collection $product->getMediaManagerUrls('documents'); // Get all URLs from documents collection // Order is preserved when syncing $product->syncMediaManagerMedia(['uuid-3', 'uuid-1', 'uuid-2']);
๐ Technical Changes
Migration Changes
media_has_models
table:- Added
order_column
(unsigned integer, nullable, indexed) - Supports rollback with proper index cleanup
- Added
View Refactoring
resources/views/forms/media-manager-picker.blade.php
- Complete rewrite with cleaner Alpine.js logic
- Removed complex nested x-data scopes
- Server-side rendering with proper ordering
- Simplified Sortable.js initialization
- Added proper instance cleanup on destroy
- Uses
wire:key
for DOM tracking - State watcher for automatic Sortable reinitialization
Backend Updates
-
src/Form/MediaManagerPicker.php
- Added
$collectionName
property andcollection()
method - Added
$generateResponsiveImages
property andresponsiveImages()
method - Added
shouldGenerateResponsiveImages()
getter method afterStateHydrated()
: Now loads and sorts media byorder_column
and filters bycollection_name
saveRelationshipsUsing()
: Saves media with sequential order values, collection name, and responsive images flag- Generates responsive images when flag is enabled
- Added
-
src/Traits/InteractsWithMediaManager.php
- Collection Name Support: All methods updated to accept optional
$collectionName
parameter getMediaManagerMedia(?string $collectionName)
: Filters by collection name and returns sorted by orderattachMediaManagerMedia(array $uuids, ?string $collectionName)
: Supports collection-specific attachmentsdetachMediaManagerMedia(?array $uuids, ?string $collectionName)
: Supports collection-specific detachmentsyncMediaManagerMedia(array $uuids, ?string $collectionName)
: Collection-aware sync operationhasMediaManagerMedia(string $uuid, ?string $collectionName)
: Collection-aware existence checkgetFirstMediaManagerMedia(?string $collectionName)
: Returns first from specific collectiongetMediaManagerUrl(?string $collectionName)
: Gets URL from specific collectiongetMediaManagerUrls(?string $collectionName)
: Gets all URLs from specific collection- New Responsive Images Methods:
getMediaManagerResponsiveImages(?string $collectionName)
: Get media with responsive datagetMediaManagerSrcset(?string $collectionName)
: Get srcset for first mediagetMediaManagerSrcsets(?string $collectionName)
: Get all srcsetsgetMediaManagerResponsiveUrls(?string $collectionName)
: Get responsive URLs for first mediagetAllMediaManagerResponsiveUrls(?string $collectionName)
: Get all responsive URLs
- Collection Name Support: All methods updated to accept optional
-
src/Livewire/MediaPicker.php
selectMedia()
: Fixed event detail structure with consistent wrapping
๐งช Testing
- โ All 97 existing tests passing
- โ Order persistence tested across all trait methods
- โ Drag and drop functionality verified
- โ State synchronization tested
- โ Collection filtering tested
- โ Backward compatibility maintained
โ ๏ธ Breaking Changes
- InteractsWithMediaManager Trait:
getMediaManagerUrl(?string $collectionName = null)
- Parameter changed from$conversion
to$collectionName
getMediaManagerUrls(?string $collectionName = null)
- Parameter changed from$conversion
to$collectionName
- If you were using these methods with conversion parameters, you'll need to update your code
- Image conversions should now be handled separately using Spatie Media Library's conversion methods
๐ Migration Guide
If upgrading from v4.0.0 or v4.0.2:
-
Run the new migrations:
php artisan migrate
This will add:
order_column
(if upgrading from v4.0.0)collection_name
columnresponsive_images
column
-
Update trait method calls if using conversions:
// Old (v4.0.0) $product->getMediaManagerUrl('thumb'); // Got thumbnail conversion // New (v4.0.3) $product->getMediaManagerUrl('gallery'); // Gets first from 'gallery' collection // For conversions, use Spatie directly: $media = $product->getFirstMediaManagerMedia('gallery'); $thumbnailUrl = $media?->getUrl('thumb');
-
Using multiple pickers on the same page:
// Now you can use collection names to separate pickers Forms\Components\MediaManagerPicker::make('featured_image') ->collection('featured') ->single(); Forms\Components\MediaManagerPicker::make('gallery_images') ->collection('gallery') ->multiple(); // Each will maintain separate media attachments
-
Using responsive images:
// Enable responsive images Forms\Components\MediaManagerPicker::make('hero_image') ->collection('hero') ->responsiveImages(); // Retrieve responsive images $srcset = $model->getMediaManagerSrcset('hero');
-
Backward Compatibility:
- Existing media without
order_column
values will still work (nullable column). Order will be applied on next save. - Existing media without
collection_name
will work as before (defaults to null) - Responsive images are opt-in via
->responsiveImages()
method
- Existing media without
Full Changelog: v4.0.2...v4.0.3