Install the Package:
composer require symfony/ux-dropzone
npm install @symfony/ux-dropzone # For frontend assets
Ensure your package.json includes the correct path to the assets directory (e.g., "assets/src").
Configure Symfony UX:
Add the bundle to config/bundles.php (Symfony) or ensure it’s auto-discovered:
return [
// ...
Symfony\UX\Dropzone\DropzoneBundle::class => ['all' => true],
];
Enable Stimulus Controller:
Register the Dropzone controller in your Stimulus configuration (e.g., assets/controllers.json):
{
"controllers": {
"dropzone": ["assets/controllers/dropzone_controller.js"]
}
}
Basic Form Integration:
Use the DropzoneType in a Symfony Form:
use Symfony\UX\Dropzone\DropzoneType;
$builder->add('files', DropzoneType::class, [
'label' => 'Upload Files',
'multiple' => true,
'mime_types' => ['image/*', 'application/pdf'],
'max_size' => '10M',
]);
Render the Form: Ensure your template includes the Stimulus bridge and Dropzone assets:
{{ include('bundles/SymfonyUxDropzone/dropzone.html.twig') }}
{{ include('bundles/SymfonyUxDropzone/dropzone_controller.html.twig') }}
Handle Uploads in Controller:
Symfony will automatically handle file uploads via UploadedFile objects:
public function upload(Request $request): Response
{
$form = $this->createFormBuilder()
->add('files', DropzoneType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$files = $form->get('files')->getData();
// Process $files (array of UploadedFile objects)
}
// ...
}
Replace a traditional file input with drag-and-drop functionality in a user profile picture upload form. This reduces friction for users uploading images and leverages Symfony’s validation pipeline for file constraints (e.g., max size, allowed types).
DropzoneType in Symfony Forms for simple drag-and-drop uploads.$builder->add('profile_picture', DropzoneType::class, [
'label' => 'Drag and drop your profile picture',
'mime_types' => ['image/jpeg', 'image/png'],
'max_size' => '2M',
'required' => false,
]);
multiple: true to allow users to upload multiple files at once.$builder->add('documents', DropzoneType::class, [
'label' => 'Upload multiple documents',
'multiple' => true,
'max_size' => '5M',
]);
// assets/controllers/dropzone_controller.js
import { Controller } from '@hotwired/stimulus';
import Dropzone from '@symfony/ux-dropzone';
export default class extends Controller {
connect() {
Dropzone.attach(this.element, {
url: this.data.get('url'),
autoProcessQueue: true,
previewTemplate: this.data.get('previewTemplate'),
});
}
}
{{ include('bundles/SymfonyUxDropzone/dropzone.html.twig', {
'url': path('app_upload'),
'previewTemplate': 'custom-preview-template.html.twig'
}) }}
File, Image, MaxSize).use Symfony\Component\Validator\Constraints as Assert;
$builder->add('resume', DropzoneType::class, [
'constraints' => [
new Assert\File([
'maxSize' => '5M',
'mimeTypes' => ['application/pdf'],
'mimeTypesMessage' => 'Please upload a PDF file',
]),
],
]);
Dropzone.attach(this.element, {
url: this.data.get('url'),
chunking: true,
chunkSize: 5 * 1024 * 1024, // 5MB chunks
parallelUploads: 4,
});
<input type="file"> if JavaScript is disabled.Form Creation:
FormFactory to create a form with DropzoneType.$form = $this->createFormBuilder()
->add('files', DropzoneType::class, [
'mime_types' => ['image/*'],
'max_size' => '10M',
])
->getForm();
Rendering the Form:
{{ form_start(form) }}
{{ form_row(form.files) }}
{{ include('bundles/SymfonyUxDropzone/dropzone.html.twig', {
'url': path('app_upload'),
}) }}
{{ form_end(form) }}
Handling Uploads:
UploadedFile objects in the controller:
public function handleUpload(Request $request): Response
{
$form = $this->createFormBuilder()
->add('files', DropzoneType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$files = $form->get('files')->getData();
foreach ($files as $file) {
$file->move($targetDir, $file->getClientOriginalName());
}
}
// ...
}
Frontend Asset Management:
// vite.config.js
export default defineConfig({
plugins: [
symfonyBridge({
entry: [
'./assets/controllers.json',
'./assets/app.js',
],
}),
],
});
Symfony Form in Laravel:
symfony/form or laravel/symfony-bridge to integrate Symfony Forms into Laravel.composer require symfony/form laravel/symfony-bridge
Blade Template Integration:
// app/Providers/AppServiceProvider.php
public function boot()
{
Blade::directive('symfonyForm', function ($expression) {
return "<?php echo \$this->renderSymfonyForm($expression); ?>";
});
}
Asset Mapping:
{# In Twig templates #}
{{ asset('bundles/symfonyuxdropzone/dropzone.css') }}
{{ asset('bundles/symfonyuxdropzone/dropzone.js') }}
Stimulus Bridge:
<script src="{{ asset('build/stimulus.js') }}"></script>
AssetMapper Integration:
asset-mapper for modern asset handling:
# config/packages/framework.yaml
framework:
assets:
packages:
dropzone:
json_manifest_path: '%kernel.project_dir%/public/build/assets.json'
Twig Extensions:
// src/Twig/Extension/DropzoneExtension.php
class DropzoneExtension extends AbstractExtension
{
public function getFunctions()
{
return [
new TwigFunction('dropzone', [$this,
How can I help you explore Laravel packages today?