Skip to content

Commit 4e75ede

Browse files
committed
feat(dropzone): enable multiple file uploads
1 parent b376eca commit 4e75ede

File tree

5 files changed

+42
-33
lines changed

5 files changed

+42
-33
lines changed

src/Dropzone/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# CHANGELOG
22

3+
## Unreleased
4+
- Support added for selecting multiple files (#???) - @daFish
5+
36
## 2.0
47

58
- Support for `stimulus` version 2 was removed and support for `@hotwired/stimulus`

src/Dropzone/Resources/assets/dist/controller.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@ class default_1 extends Controller {
1515
this.previewImageTarget.style.display = 'none';
1616
this.previewImageTarget.style.backgroundImage = 'none';
1717
this.previewFilenameTarget.textContent = '';
18+
document.querySelectorAll('.dropzone-preview-image-container').forEach(e => e.remove());
1819
this._dispatchEvent('dropzone:clear');
1920
}
2021
onInputChange(event) {
21-
const file = event.target.files[0];
22-
if (typeof file === 'undefined') {
23-
return;
24-
}
25-
this.inputTarget.style.display = 'none';
26-
this.placeholderTarget.style.display = 'none';
27-
this.previewFilenameTarget.textContent = file.name;
28-
this.previewTarget.style.display = 'flex';
29-
this.previewImageTarget.style.display = 'none';
30-
if (file.type && file.type.indexOf('image') !== -1) {
31-
this._populateImagePreview(file);
22+
for (const fileItem in event.target.files) {
23+
const file = event.target.files[fileItem];
24+
if (typeof file === 'undefined') {
25+
return;
26+
}
27+
this.inputTarget.style.display = 'none';
28+
this.placeholderTarget.style.display = 'none';
29+
this.previewFilenameTarget.textContent = file.name;
30+
this.previewTarget.style.display = 'flex';
31+
this.previewImageTarget.style.display = 'none';
32+
if (file.type && file.type.indexOf('image') !== -1) {
33+
this._populateImagePreview(file);
34+
}
35+
this._dispatchEvent('dropzone:change', file);
3236
}
33-
this._dispatchEvent('dropzone:change', file);
3437
}
3538
_populateImagePreview(file) {
3639
if (typeof FileReader === 'undefined') {

src/Dropzone/Resources/assets/src/controller.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,34 @@ export default class extends Controller {
4242
this.previewImageTarget.style.display = 'none';
4343
this.previewImageTarget.style.backgroundImage = 'none';
4444
this.previewFilenameTarget.textContent = '';
45+
document.querySelectorAll('.dropzone-preview-image-container').forEach(e => e.remove());
4546

4647
this._dispatchEvent('dropzone:clear');
4748
}
4849

4950
onInputChange(event: any) {
50-
const file = event.target.files[0];
51-
if (typeof file === 'undefined') {
52-
return;
51+
for (const fileItem in event.target.files) {
52+
const file = event.target.files[fileItem];
53+
if (typeof file === 'undefined') {
54+
return;
55+
}
56+
57+
// Hide the input and placeholder
58+
this.inputTarget.style.display = 'none';
59+
this.placeholderTarget.style.display = 'none';
60+
61+
// Show the filename in preview
62+
this.previewFilenameTarget.textContent = file.name;
63+
this.previewTarget.style.display = 'flex';
64+
65+
// If the file is an image, load it and display it as preview
66+
this.previewImageTarget.style.display = 'none';
67+
if (file.type && file.type.indexOf('image') !== -1) {
68+
this._populateImagePreview(file);
69+
}
70+
71+
this._dispatchEvent('dropzone:change', file);
5372
}
54-
55-
// Hide the input and placeholder
56-
this.inputTarget.style.display = 'none';
57-
this.placeholderTarget.style.display = 'none';
58-
59-
// Show the filename in preview
60-
this.previewFilenameTarget.textContent = file.name;
61-
this.previewTarget.style.display = 'flex';
62-
63-
// If the file is an image, load it and display it as preview
64-
this.previewImageTarget.style.display = 'none';
65-
if (file.type && file.type.indexOf('image') !== -1) {
66-
this._populateImagePreview(file);
67-
}
68-
69-
this._dispatchEvent('dropzone:change', file);
7073
}
7174

7275
_populateImagePreview(file: Blob) {

src/Dropzone/Resources/assets/test/controller.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('DropzoneController', () => {
3939
<input type="file"
4040
style="display: none"
4141
data-dropzone-target="input"
42-
data-testid="input" />
42+
data-testid="input" multiple />
4343
4444
<div class="dropzone-placeholder"
4545
data-dropzone-target="placeholder"

src/Dropzone/Resources/views/form_theme.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{%- set attr = attr|merge({ 'data-controller': '', class: (attr.class|default('') ~ ' dropzone-input')|trim}) -%}
44

55
<div class="dropzone-container" data-controller="{{ dataController }}">
6-
<input type="file" {{ block('widget_attributes') }} data-symfony--ux-dropzone--dropzone-target="input" />
6+
<input type="file" {{ block('widget_attributes') }} data-symfony--ux-dropzone--dropzone-target="input" multiple />
77

88
<div class="dropzone-placeholder" data-symfony--ux-dropzone--dropzone-target="placeholder">
99
{%- if attr.placeholder is defined and attr.placeholder is not none -%}

0 commit comments

Comments
 (0)