I’m positing this again in case it went un-noticed before.
I have file field with direct upload enabled in my form. When user uploads files and clicks the submit button while the files still uploading (slow internet, big files etc), the form submits but the submission have empty entry (or have some tmp folder url’s with some code with them) where just the file url’s should show up.
Digging deeper in the server I can find the file(s) that “failed” to upload inside the bricksforge/tmp folder in main uploads folder.
Anyway, would be great if the form would wait until all the files are uploaded or some kind of safeguard for that. Thank you.
I vibe coded my own solution and posting it here in case somebody else needs it.
Sometimes users are uploading large files with a slow internet speeds, and with the direct upload option enabled they were able to submit form even if the files was not completely uploaded yet, and that might cause some issues in your systems or submissions etc.
With this solution - as soon as user drops a file to the upload area, it locks the form submit button until the file is completely uploaded, and then unlocks it again. Feel free to try it out and edit as needed.
Instructions. Select your Pro form, and go to Style > CSS and give it a CSS ID “my-upload-form”
Then insert a code block right after the Pro Forms element and paste the following code in it, sign and activate. Make sure you have a file field in your form and “direct upload to server” option activated for it.
Code for a code block:
<script>
document.addEventListener('DOMContentLoaded', function() {
const formId = 'my-upload-form';
const form = document.getElementById(formId);
if (!form) return;
const submitBtn = form.querySelector('button[type="submit"]');
if (!submitBtn) return;
// Save original text
const originalText = submitBtn.dataset.originalText || submitBtn.innerHTML;
submitBtn.dataset.originalText = originalText;
// VARIABLES TO BRIDGE THE GAP
let manualLockActive = false;
let bridgeTimer = null;
// --- 1. LOCK/UNLOCK HELPERS ---
const lockButton = (text) => {
submitBtn.disabled = true;
submitBtn.style.opacity = '0.5';
submitBtn.style.cursor = 'wait';
// Only update text if changed (prevents jitter)
if (submitBtn.innerHTML !== text) submitBtn.innerHTML = text;
};
const unlockButton = () => {
// Only unlock if strict conditions are met
if (submitBtn.disabled) {
submitBtn.disabled = false;
submitBtn.style.opacity = '1';
submitBtn.style.cursor = 'pointer';
submitBtn.innerHTML = originalText;
}
};
// --- 2. THE LOGIC BRAIN ---
const checkStatus = () => {
// A. If the "Bridge Timer" is active, DO NOT UNLOCK.
if (manualLockActive) {
lockButton('Preparing...');
return;
}
// B. Check DOM for real upload status
const items = form.querySelectorAll('[data-filepond-item-state*="processing"]');
let activelyUploading = false;
items.forEach(item => {
const state = item.getAttribute('data-filepond-item-state');
// We lock on 'processing', 'queued', or 'loading'
if (state && (state.includes('processing') || state.includes('load'))) {
// Ignore 'complete' or 'error'
if (!state.includes('complete') && !state.includes('error')) {
activelyUploading = true;
}
}
});
if (activelyUploading) {
lockButton('Uploading...');
} else {
unlockButton();
}
};
// --- 3. THE INSTANT TRIGGER (Gap Bridging) ---
const activateBridgeLock = () => {
console.log('Instant Lock Triggered');
// 1. Force Lock immediately
manualLockActive = true;
lockButton('Preparing...');
// 2. Clear previous timer if exists
if (bridgeTimer) clearTimeout(bridgeTimer);
// 3. Keep manual lock for 2 seconds to allow FilePond to initialize the upload
bridgeTimer = setTimeout(() => {
console.log('Bridge Timer ended - Handing over to Observer');
manualLockActive = false; // Release manual hold
checkStatus(); // Let the DOM state take over
}, 2000);
};
// --- 4. LISTENERS ---
// Detect Drop
form.addEventListener('drop', (e) => {
if (e.target.closest('.filepond--root')) {
activateBridgeLock();
}
}, true);
// Detect File Select (Browse)
form.addEventListener('change', (e) => {
if (e.target.type === 'file') {
activateBridgeLock();
}
}, true);
// Observer to watch for progress
const observer = new MutationObserver((mutations) => {
// We delay slightly to let the DOM settle
// But the 'manualLockActive' will prevent unlocking during this time
setTimeout(checkStatus, 20);
});
observer.observe(form, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ['data-filepond-item-state']
});
// --- 5. SAFETY CLICK BLOCKER ---
submitBtn.addEventListener('click', (e) => {
if (manualLockActive || submitBtn.innerHTML === 'Uploading...') {
e.preventDefault();
e.stopImmediatePropagation();
console.log("Submission blocked by Guard");
}
});
});
</script>