dasundev/livewire-dropzone
Livewire Dropzone adds an easy drag-and-drop upload area to Laravel Livewire apps. Supports simple file selection and drop uploads with a reusable component, helping you build modern upload UX quickly with minimal setup.
Installation:
composer require dasundev/livewire-dropzone
Publish assets (if needed):
npm install && npm run dev
Basic Usage: Create a Livewire component:
php artisan make:livewire FileUpload
Add the Dropzone component to your Blade view:
<livewire:file-upload />
Implement the component logic:
// app/Http/Livewire/FileUpload.php
use DasunDev\LivewireDropzone\LivewireDropzone;
public function mount()
{
$this->file = null;
}
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'file' => 'nullable|array',
'file.*' => 'image|mimes:jpeg,png,jpg,gif|max:1024',
]);
}
public function render()
{
return view('livewire.file-upload', [
'files' => $this->file,
]);
}
View Integration:
<livewire-dropzone
wire:model="file"
upload-url="{{ route('upload') }}"
max-files="1"
accept="image/*"
/>
Replace traditional file inputs with a seamless drag-and-drop interface for image uploads in a user profile component.
<livewire-dropzone
wire:model="profileImage"
upload-url="{{ route('profile.upload') }}"
max-files="1"
accept="image/*"
with-credentials="true"
/>
// Component
public $files = [];
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'files' => 'nullable|array',
'files.*' => 'file|max:1024',
]);
}
<livewire-dropzone
wire:model="files"
upload-url="{{ route('files.upload') }}"
max-files="5"
accept="image/*,application/pdf"
/>
protected $rules = [
'file' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
];
public function upload()
{
if ($this->validate()) {
$path = $this->file->store('uploads');
// Process file (e.g., generate thumbnail)
event(new FileUploaded($this->file, $path));
}
}
<livewire-dropzone
:config="dropzoneConfig"
wire:model="documents"
/>
// Component
public function getDropzoneConfigProperty()
{
return [
'url' => route('documents.upload'),
'maxFilesize' => 5, // MB
'acceptedFiles' => 'application/pdf,image/*',
'autoProcessQueue' => true,
];
}
protected $listeners = ['fileUploaded' => 'handleUpload'];
public function handleUpload($event)
{
$this->emit('alert', 'File uploaded successfully!');
}
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'file' => [
'required',
'file',
Rule::unique('media')->where(fn ($query) => $query->where('model_type', self::class)),
],
]);
}
// Dispatch from component
$this->emit('fileUploadProgress', $percentage);
// Listen in parent component
protected $listeners = ['fileUploadProgress' => 'updateProgress'];
// Component
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'file' => 'required|file|max:10240', // 10MB
]);
if ($this->file) {
$chunkSize = 2 * 1024 * 1024; // 2MB chunks
$this->uploadInChunks($this->file->path(), $chunkSize);
}
}
CSRF Token Mismatch
@csrf token if using traditional form submission:
<livewire-dropzone
upload-url="{{ route('upload') }}?{{ csrf_token() }}"
/>
File Size Limits
post_max_size and upload_max_filesize must exceed your Dropzone limits:
; php.ini
upload_max_filesize = 20M
post_max_size = 25M
Multiple Dropzones on Page
unique-id to avoid event conflicts:
<livewire-dropzone unique-id="profile-upload" ... />
Temporary File Cleanup
// After processing
Storage::delete($tempPath);
Network Tab Inspection
X-Requested-With: Livewire header in browser dev tools to verify Livewire requests.Event Listening
wire:ignore on parent containers to prevent event bubbling issues:
<div wire:ignore>
<livewire-dropzone ... />
</div>
Validation Errors
updated() method to show errors immediately:
public function updated($propertyName)
{
$this->validateOnly($propertyName, [
'file' => 'required|mimes:jpeg,png|max:1024',
]);
}
Custom Upload URLs
<livewire-dropzone upload-url="{{ config('app.url').'/api/upload' }}" />
CORS Issues
// Middleware
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Access-Control-Allow-Methods', 'POST, OPTIONS');
File Preview Limitations
<livewire-dropzone preview="false" ... />
Custom Templates
php artisan vendor:publish --tag=livewire-dropzone-views
resources/views/vendor/livewire-dropzone/dropzone.blade.php.Alpine.js Integration
<livewire-dropzone
x-data="{ isProcessing: false }"
@processing.window="isProcessing = true"
@complete.window="isProcessing = false"
/>
Progress Tracking
// Component
public $uploadProgress = 0;
public function updated($propertyName)
{
$this->validateOnly($propertyName, [...]);
if ($this->file) {
$this->uploadProgress = 0;
$this->emit('uploadStarted');
}
}
// Blade
<progress x-show="isProcessing" :value="uploadProgress" max="100">
{{ uploadProgress }}%
</progress>
File Metadata
updated():
public function updated($propertyName)
{
if ($this->file) {
$file = $this->file[0];
$this->emit('fileMetadata', [
'name' => $file->getClientOriginalName(),
'size' => $file->getSize(),
'mime' => $file->getMimeType(),
]);
}
}
Fallback for Old Browsers
@if(config('app.debug'))
<livewire-dropzone ... />
@else
<input type="file" wire:model="file" />
@endif
How can I help you explore Laravel packages today?