I have a form that takes file uploads and it currently has a limit of 10 files per upload. There are PHP validations in the backend for this too.
When more than 10 files are attached, I currently have a JavaScript slice(0, 10)
method inside a change
event for the file input element, which removes any files (and their preview image thumbnails) when the number attached is more than 10 files.
// For each added file, add it to submitData (the DataTransfer Object), if not already present
[...e.target.files].slice(0,10).forEach((file) => {
if (currentSubmitData.every((currFile) => currFile.name !== file.name)) {
submitData.items.add(file);
}
});
The Issue
What I can’t seem to do though is work out a way to slice()
the files array in a compound attachment situation, i.e. if 8 files are attached initially, and then the user decides to add another 4 prior to submitting the form, taking the total to 12. The current slice only happens when more than 10 are added in one go.
I have a decode()
method that runs inside a loop (for every image attached) that carries out frontend validations, and a promiseAllSettled()
method that waits for the last image to be attached prior to outputting a main error message telling the user to check the specific errors on the page.
Question
How do I slice the array on the total number of files appended, if the user has initially attached a file count less than 10, then attaches further files taking it more than 10 prior to form submission?
const attachFiles = document.getElementById('attach-files'), // file input element
dropZone = document.getElementById('dropzone'),
submitData = new DataTransfer();
dropZone.addEventListener('click', () => {
// assigns the dropzone to the hidden 'files' input element/file picker
attachFiles.click();
});
attachFiles.addEventListener('change', (e) => {
const currentSubmitData = Array.from(submitData.files);
console.log(e.target.files.length);
// For each added file, add it to 'submitData' if not already present (maximum of 10 files with slice(0, 10)
[...e.target.files].slice(0,10).forEach((file) => {
if (currentSubmitData.every((currFile) => currFile.name !== file.name)) {
submitData.items.add(file);
}
});
// Sync attachFiles FileList with submitData FileList
attachFiles.files = submitData.files;
// Clear the previewWrapper before generating new previews
previewWrapper.replaceChildren();
// the 'decode()' function inside the 'showFiles()' function is returned
// we wait for all of the promises for each image to settle
Promise.allSettled([...submitData.files].map(showFiles)).then((results) => {
// output main error message at top of page alerting user to error messages attached to images
});
}); // end of 'change' event listener
function showFiles(file) {
// code to generate image previews and append them to the 'previewWrapper'
// then use the decode() method that returns a promise and do JS validations on the preview images
return previewImage.decode().then(() => {
// preform JS validations and append
}).catch((error) => {
console.log(error)
});
} // end of showfiles(file)