In Big Sexy Poems, I have an Alpine.js directive that binds to my ColdFusion forms, listens for the submit event, and prevents accidental double-submission by setting a flag and disabling the submit button(s). After I started using this directive, I noticed that my forms would remain disabled when I navigated back to them using the browser’s Back Button. This is because the browser pulls the ColdFusion form page out of the “bfcache”, which re-renders whatever state the page was in at the previou…
In Big Sexy Poems, I have an Alpine.js directive that binds to my ColdFusion forms, listens for the submit event, and prevents accidental double-submission by setting a flag and disabling the submit button(s). After I started using this directive, I noticed that my forms would remain disabled when I navigated back to them using the browser’s Back Button. This is because the browser pulls the ColdFusion form page out of the “bfcache”, which re-renders whatever state the page was in at the previous point of unload.
To see this in action, I’ve created a very simple form with an input and a submit button. I then bind to the submit event and put in double-submission control flow logic:
<form method="post" action="form-success.cfm">
<input
type="text"
name="name"
size="30"
/>
<button type="submit">
Save Changes
</button>
</form>
<script type="text/javascript">
var form = document.querySelector( "form" );
var button = form.querySelector( "button" );
// Listen for the form submission event in order to prevent accidental double-
// submission of data (usually from the user clicking the submit button twice).
form.addEventListener( "submit", ( event ) => {
if ( ! form.dataset.isSubmitting ) {
form.dataset.isSubmitting = "true";
button.disabled = true;
}
});
</script>
If we now submit the form and then navigate back to it using the browser’s back button, you’ll see that the submit button remains disabled and the isSubmitting flag still exists in the dataset:
Keeping the ColdFusion form in a disabled state may make sense in some edge-cases (specifically when you don’t want the user to navigate back to the form because its state may now be invalid / expired); but, until it becomes a problem, I always want the form to be re-enabled regardless of the how the user gets there.
To put my ColdFusion forms back into a good state, I started listening to the pageshow event. This event — which I just learned about — is triggered whenever the browser renders a page due to navigation. And includes a persisted property, indicating whether or not the page was pulled from the cache.
In this next version of the page form, I’m adding pageshow event handling that removes the cached double-submission state upon re-rendering:
<form method="post" action="form-success.cfm">
<input
type="text"
name="name"
size="30"
/>
<button type="submit">
Save Changes
</button>
</form>
<script type="text/javascript">
var form = document.querySelector( "form" );
var button = form.querySelector( "button" );
// Listen for the form submission event in order to prevent accidental double-
// submission of data (usually from the user clicking the submit button twice).
form.addEventListener( "submit", ( event ) => {
if ( ! form.dataset.isSubmitting ) {
form.dataset.isSubmitting = "true";
button.disabled = true;
}
});
// If the user navigates to this form using the BACK BUTTON and the page was pulled
// from the bfcache (Back/Forward browser cache), then the form will likely be
// rendered with the double-submission block (from above) still in place. In order to
// re-enable the form, listen for the "pageshow" event (with a "persisted" status) and
// explicitly remove the double-submissions blocks.
window.addEventListener( "pageshow", ( event ) => {
if ( event.persisted && form.dataset.isSubmitting ) {
delete form.dataset.isSubmitting;
button.disabled = false;
}
});
</script>
Now, if we perform the same actions on this form, submitting it and then navigating back to it, we’ll see that the form is returned to a valid state:
Before I learned about the pageshow event, my first instinct was to just strip-out any double-submission artifacts during page initialization. The problem with this is that the page doesn’t initialize when it’s pulled from the “bfcache” — the entire cached state is returned, including both the DOM (Document Object Model) tree and the JavaScript memory. In other words, returning to the page via the “bfcache” is like returning to the moment in time just prior to the page unload event.
In Big Sexy Poems, I’m not hand-coding this for every form. Instead, I have an x-prevent-double-submit directive that I include on every <form> element. This directive includes both the double-submission logic and the pageshow logic.
Want to use code from this post? Check out the license.
I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
— Ben Nadel Managed hosting services provided by: