Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Livewire Filepond
https://github.com/spatie/livewire-filepond
Admin
A Livewire component that integrates the Filepond JavaScript library for easy file uploads in
...
Tokens:
7,033
Snippets:
38
Trust Score:
8.5
Update:
4 months ago
Context
Skills
Chat
Benchmark
76.3
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Livewire FilePond Livewire FilePond is a Laravel package that provides seamless integration between FilePond (a powerful JavaScript file upload library) and Livewire components. It enables developers to implement modern drag-and-drop file uploads with minimal configuration, wrapping FilePond's rich feature set into a simple Livewire-compatible component. The package handles the complexity of bridging client-side file uploads with server-side Livewire state management, providing automatic validation, temporary file handling, and event-driven workflows. Built by Spatie and used in production in their Mailcoach product, this package supports Laravel 10.x/11.x/12.x and Livewire 3.5+. It includes 40+ language translations, multiple FilePond plugins for image processing (preview, crop, resize, transform), and comprehensive file validation capabilities. The package offers both dynamic asset serving through Laravel routes and optional static asset publishing for CDN deployment. ## Basic File Upload Component Simple file upload with drag-and-drop interface ```php // app/Livewire/DocumentUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; class DocumentUpload extends Component { use WithFilePond; public $document; public function save() { // $this->document is a TemporaryUploadedFile instance $path = $this->document->store('documents', 'public'); // Store to database or process further auth()->user()->documents()->create([ 'path' => $path, 'filename' => $this->document->getClientOriginalName(), ]); $this->resetFilePond('document'); session()->flash('message', 'Document uploaded successfully!'); } public function render() { return view('livewire.document-upload'); } } ``` ```blade {{-- resources/views/livewire/document-upload.blade.php --}} <div> @if (session()->has('message')) <div class="alert alert-success"> {{ session('message') }} </div> @endif <x-filepond::upload wire:model="document" /> <button wire:click="save" type="button"> Save Document </button> </div> ``` ```blade {{-- resources/views/layouts/app.blade.php --}} <!DOCTYPE html> <html> <head> <title>My App</title> @filepondScripts </head> <body> @livewire('document-upload') </body> </html> ``` ## Multiple File Upload Upload multiple files simultaneously with array handling ```php // app/Livewire/GalleryUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; class GalleryUpload extends Component { use WithFilePond; public $photos = []; public function save() { // $this->photos is an array of TemporaryUploadedFile instances foreach ($this->photos as $photo) { $path = $photo->store('gallery', 'public'); auth()->user()->photos()->create([ 'path' => $path, 'filename' => $photo->getClientOriginalName(), 'size' => $photo->getSize(), ]); } $this->resetFilePond('photos'); session()->flash('message', count($this->photos) . ' photos uploaded!'); } public function render() { return view('livewire.gallery-upload'); } } ``` ```blade {{-- resources/views/livewire/gallery-upload.blade.php --}} <div> <x-filepond::upload wire:model="photos" multiple max-files="10" accepted-file-types="image/png, image/jpeg, image/jpg" /> @if (count($photos) > 0) <p>{{ count($photos) }} file(s) selected</p> <button wire:click="save" type="button"> Upload {{ count($photos) }} Photo(s) </button> @endif </div> ``` ## Server-Side Validation on Upload Validate files immediately upon upload with custom rules ```php // app/Livewire/AvatarUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; class AvatarUpload extends Component { use WithFilePond; public $avatar; public function rules(): array { return [ 'avatar' => 'required|image|mimetypes:image/jpg,image/jpeg,image/png|max:3000', ]; } public function messages(): array { return [ 'avatar.required' => 'Please upload an avatar image.', 'avatar.image' => 'The file must be an image.', 'avatar.mimetypes' => 'Only JPG, JPEG, and PNG images are allowed.', 'avatar.max' => 'The image must not exceed 3MB.', ]; } public function validateUploadedFile(): bool { // This is called automatically after each file upload // If validation fails, the upload is rejected immediately $this->validate(); return true; } public function save() { $this->validate(); // Delete old avatar if exists if (auth()->user()->avatar) { Storage::disk('public')->delete(auth()->user()->avatar); } // Store new avatar $path = $this->avatar->store('avatars', 'public'); auth()->user()->update(['avatar' => $path]); $this->resetFilePond('avatar'); session()->flash('message', 'Avatar updated successfully!'); } public function render() { return view('livewire.avatar-upload'); } } ``` ```blade {{-- resources/views/livewire/avatar-upload.blade.php --}} <div> @error('avatar') <div class="alert alert-error">{{ $message }}</div> @enderror <x-filepond::upload wire:model="avatar" required max-files="1" accepted-file-types="image/png, image/jpeg, image/jpg" image-crop-aspect-ratio="1:1" style-panel-layout="compact circle" /> @if ($avatar) <button wire:click="save" type="button"> Save Avatar </button> @endif </div> ``` ## Pre-loading Existing Files Display previously uploaded files in FilePond component ```php // app/Livewire/DocumentEditor.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; use App\Models\Document; class DocumentEditor extends Component { use WithFilePond; public Document $document; public $file; public function mount(Document $document) { $this->document = $document; // Pre-populate with existing file URL // The component will automatically load and display it $this->file = asset('storage/' . $document->path); } public function update() { // Only update if a new file was uploaded if ($this->file instanceof \Livewire\Features\SupportFileUploads\TemporaryUploadedFile) { // Delete old file Storage::disk('public')->delete($this->document->path); // Store new file $path = $this->file->store('documents', 'public'); $this->document->update([ 'path' => $path, 'filename' => $this->file->getClientOriginalName(), ]); } session()->flash('message', 'Document updated successfully!'); } public function render() { return view('livewire.document-editor'); } } ``` ```blade {{-- resources/views/livewire/document-editor.blade.php --}} <div> <h2>Edit Document: {{ $document->filename }}</h2> <x-filepond::upload wire:model="file" /> <button wire:click="update" type="button"> Update Document </button> </div> ``` ## Event Handling with Alpine.js Listen to upload events and trigger custom actions ```blade {{-- resources/views/livewire/file-upload-with-events.blade.php --}} <div x-data="{ uploading: false, uploadedCount: 0, completed: false }"> <div x-show="uploading" class="upload-progress"> <p>Uploading files... Please wait.</p> </div> <div x-show="completed" class="upload-complete"> <p>All {{ uploadedCount }} file(s) uploaded successfully!</p> </div> <x-filepond::upload wire:model="files" multiple @filepond-upload-started="uploading = true" @filepond-upload-finished="uploadedCount++" @filepond-upload-reverted="uploadedCount--" @filepond-upload-file-removed="console.log('File removed')" @filepond-upload-completed="uploading = false; completed = true" /> </div> ``` ```php // app/Livewire/FileUploadWithEvents.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; class FileUploadWithEvents extends Component { use WithFilePond; public $files = []; public function render() { return view('livewire.file-upload-with-events'); } } ``` ## Advanced FilePond Configuration Customize FilePond with image processing and constraints ```blade {{-- resources/views/livewire/product-image-upload.blade.php --}} <div> <x-filepond::upload wire:model="productImages" multiple max-files="5" max-file-size="5MB" accepted-file-types="image/png, image/jpeg, image/webp" allow-image-preview="true" allow-image-crop="true" allow-image-resize="true" image-crop-aspect-ratio="16:9" image-resize-target-width="1920" image-resize-target-height="1080" image-resize-mode="contain" image-resize-upscale="false" instant-upload="false" credits="false" placeholder="Drop product images here (max 5 files, 16:9 ratio)" /> </div> ``` ```php // app/Livewire/ProductImageUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; use App\Models\Product; class ProductImageUpload extends Component { use WithFilePond; public Product $product; public $productImages = []; public function rules(): array { return [ 'productImages.*' => 'image|mimetypes:image/png,image/jpeg,image/webp|max:5120', ]; } public function validateUploadedFile(): bool { $this->validate(); return true; } public function save() { $this->validate(); foreach ($this->productImages as $image) { $path = $image->store('products/' . $this->product->id, 'public'); $this->product->images()->create([ 'path' => $path, 'filename' => $image->getClientOriginalName(), 'order' => $this->product->images()->count(), ]); } $this->resetFilePond('productImages'); session()->flash('message', 'Product images uploaded!'); } public function render() { return view('livewire.product-image-upload'); } } ``` ## Manual FilePond Reset Programmatically clear FilePond component ```php // app/Livewire/BatchUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; class BatchUpload extends Component { use WithFilePond; public $documents = []; public $uploadedCount = 0; public function save() { foreach ($this->documents as $document) { $path = $document->store('batch-uploads', 'public'); auth()->user()->documents()->create([ 'path' => $path, 'filename' => $document->getClientOriginalName(), ]); $this->uploadedCount++; } // Clear the FilePond component and reset the property $this->resetFilePond('documents'); session()->flash('message', 'Batch upload completed!'); } public function clearAll() { // Manually reset FilePond without saving $this->resetFilePond('documents'); session()->flash('message', 'Upload cancelled.'); } public function render() { return view('livewire.batch-upload'); } } ``` ```blade {{-- resources/views/livewire/batch-upload.blade.php --}} <div> <p>Total uploaded in this session: {{ $uploadedCount }}</p> <x-filepond::upload wire:model="documents" multiple /> @if (count($documents) > 0) <button wire:click="save" type="button"> Save {{ count($documents) }} Document(s) </button> <button wire:click="clearAll" type="button"> Clear All </button> @endif </div> ``` ## WithFilePond Trait Methods Core trait providing file handling functionality ```php // Trait usage example <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; class FileManager extends Component { use WithFilePond; public $files = []; /** * Called automatically by FilePond after file upload * Override to implement custom validation logic * * @return bool Returns true if validation passes, false otherwise */ public function validateUploadedFile(): bool { // Default implementation returns true // Override with custom validation: $this->validate([ 'files.*' => 'required|file|max:10240', ]); return true; } /** * Remove a file from the property and delete from storage * Called when user clicks remove button in FilePond * * @param string $property The Livewire property name * @param string $filename The filename to remove */ public function customRemove($property, $filename) { // The trait's remove() method handles this automatically // You typically don't need to call this manually $this->remove($property, $filename); } /** * Revert an uploaded file (undo upload) * Called when user clicks undo button in FilePond * * @param string $property The Livewire property name * @param string $filename The filename to revert */ public function customRevert($property, $filename) { // The trait's revert() method handles this automatically // It deletes the TemporaryUploadedFile and updates the property $this->revert($property, $filename); } /** * Reset FilePond component and clear files * Call this after processing uploads or to cancel * * @param string $property The Livewire property name to reset */ public function clearUploads() { $this->resetFilePond('files'); // This method: // 1. Resets the Livewire property to null/empty array // 2. Dispatches 'filepond-reset-{property}' event to clear UI } public function render() { return view('livewire.file-manager'); } } ``` ## Localization Configure FilePond in different languages ```bash # Publish translation files php artisan vendor:publish --tag="livewire-filepond-translations" ``` ```env # .env - Set application locale APP_LOCALE=id ``` ```php // config/app.php or in a middleware use Illuminate\Support\Facades\App; // Set locale programmatically App::setLocale('id'); // Indonesian App::setLocale('es'); // Spanish App::setLocale('fr'); // French App::setLocale('de'); // German ``` ```php // resources/lang/id/filepond.php (after publishing) <?php return [ 'labelIdle' => 'Seret & Lepas file Anda atau <span class="filepond--label-action"> Telusuri </span>', 'labelFileLoading' => 'Memuat', 'labelFileProcessing' => 'Mengunggah', 'labelFileProcessingComplete' => 'Upload selesai', 'labelFileProcessingAborted' => 'Upload dibatalkan', 'labelTapToCancel' => 'ketuk untuk membatalkan', 'labelTapToRetry' => 'ketuk untuk mencoba lagi', 'labelTapToUndo' => 'ketuk untuk membatalkan', 'labelButtonRemoveItem' => 'Hapus', 'labelButtonAbortItemLoad' => 'Batalkan', 'labelButtonRetryItemLoad' => 'Coba lagi', 'labelButtonAbortItemProcessing' => 'Batalkan', 'labelButtonUndoItemProcessing' => 'Urungkan', 'labelButtonRetryItemProcessing' => 'Coba lagi', 'labelButtonProcessItem' => 'Upload', ]; ``` ```php // app/Livewire/LocalizedUpload.php <?php namespace App\Livewire; use Livewire\Component; use Spatie\LivewireFilepond\WithFilePond; use Illuminate\Support\Facades\App; class LocalizedUpload extends Component { use WithFilePond; public $file; public $locale = 'en'; public function updatedLocale($value) { App::setLocale($value); // Re-render component with new locale $this->dispatch('$refresh'); } public function render() { return view('livewire.localized-upload'); } } ``` ## Static Asset Publishing Serve FilePond assets from your public directory ```bash # Publish static assets to public/vendor/livewire-filepond php artisan vendor:publish --tag=livewire-filepond-assets --force ``` ```json // composer.json - Auto-publish assets after updates { "scripts": { "post-update-cmd": [ "@php artisan vendor:publish --tag=livewire-filepond-assets --force" ] } } ``` ```blade {{-- After publishing, assets are served from: --}} {{-- public/vendor/livewire-filepond/filepond.js --}} {{-- public/vendor/livewire-filepond/filepond.css --}} {{-- The @filepondScripts directive automatically detects published assets --}} @filepondScripts ``` ## Installation and Setup Complete installation guide ```bash # Install via Composer composer require spatie/livewire-filepond # Optional: Publish views for customization php artisan vendor:publish --tag="livewire-filepond-views" # Optional: Publish translations for customization php artisan vendor:publish --tag="livewire-filepond-translations" # Optional: Publish assets for static serving php artisan vendor:publish --tag="livewire-filepond-assets" --force ``` ```php // The service provider is auto-discovered via Laravel's package discovery // No manual registration needed // Verify installation in config/app.php (auto-added): 'providers' => [ // ... Spatie\LivewireFilepond\LivewireFilepondServiceProvider::class, ], ``` ```blade {{-- resources/views/layouts/app.blade.php --}} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Application</title> {{-- Required: Add FilePond scripts and styles --}} @filepondScripts @livewireStyles </head> <body> {{ $slot }} @livewireScripts </body> </html> ``` ## Summary Livewire FilePond simplifies file upload implementation in Laravel applications by providing a drop-in Livewire component that wraps FilePond's rich JavaScript library. The package excels at handling common upload scenarios including single and multiple file uploads, image processing with crop/resize/transform capabilities, real-time validation, and pre-loading existing files. With support for 40+ languages and comprehensive event handling through Alpine.js, developers can create sophisticated file upload interfaces with minimal custom code. The `WithFilePond` trait extends Livewire's native file upload functionality with methods for reverting uploads, removing files, and resetting the component state, while the `validateUploadedFile()` hook enables immediate server-side validation as files are uploaded. The package's flexible architecture supports both dynamic asset serving through Laravel routes and static asset publishing for CDN deployment, making it suitable for various hosting environments. Integration requires only three steps: adding the `@filepondScripts` directive to your layout, including the `WithFilePond` trait in your Livewire component, and placing the `<x-filepond::upload>` component in your view with a `wire:model` binding. FilePond's extensive configuration options are accessible via kebab-case attributes on the Blade component, allowing fine-grained control over file constraints, image processing, and UI behavior. Whether building a simple document upload form or a complex multi-file image gallery with validation and processing, Livewire FilePond provides the tools needed for modern file upload experiences in Laravel applications.