Skip to content

Commit

Permalink
prevent double click form submit with javascript
Browse files Browse the repository at this point in the history
  • Loading branch information
bseber committed Jul 5, 2024
1 parent cbcff01 commit 30ce337
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/main/javascript/bundles/user-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "../components/details-dropdown";
import "../components/feedback-form";
import "../components/navigation";
import "../components/time-clock";
import { initPreventDoubleClickSubmit } from "../components/form";
import { initFeedbackHeartView } from "../components/feedback-heart";

const showFeedbackKudo =
Expand All @@ -15,3 +16,5 @@ initFeedbackHeartView({
showFeedbackKudo: showFeedbackKudo,
},
});

initPreventDoubleClickSubmit();
1 change: 1 addition & 0 deletions src/main/javascript/components/form/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./autosubmit";
export * from "./prevent-double-click-submit";
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
afterEach,
beforeAll,
beforeEach,
describe,
expect,
test,
} from "vitest";
import { initPreventDoubleClickSubmit } from "./prevent-double-click-submit";

describe("DoubleClickSubmitGuard", () => {
beforeAll(() => {
initPreventDoubleClickSubmit();
});

beforeEach(() => {
// prevent HTMLFormElement.prototype.requestSubmit is not implemented log.
//
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
window._virtualConsole.emit = () => {};
});

afterEach(() => {
while (document.body.firstChild) {
document.body.firstChild.remove();
}
});

test("disables submitter on form submit", () => {
document.body.innerHTML = `
<form action="#">
<button type="submit">Submit</button>
</form>
`;

const button = document.querySelector("button");

expect(button.getAttribute("disabled")).toBeNull();

button.click();

expect(button.getAttribute("disabled")).toBe("");
});

test("does not disable submitter on form submit when defaultPrevented", () => {
document.body.innerHTML = `
<form action="#">
<button type="submit">Submit</button>
</form>
`;

let called = false;

document.querySelector("form").addEventListener("submit", function (event) {
event.preventDefault();
called = true;
});

const button = document.querySelector("button");

button.click();

expect(button.getAttribute("disabled")).toBeNull();
expect(called).toBe(true);
});
});
13 changes: 13 additions & 0 deletions src/main/javascript/components/form/prevent-double-click-submit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Adds a global `submit` listener and disables the submitter.
*/
export function initPreventDoubleClickSubmit() {
window.addEventListener("submit", function (event) {
if (!event.defaultPrevented) {
event.submitter?.setAttribute("disabled", "");
// full page reload renders the form again with enabled submitter.
// maybe @hotwired/turbo is enabled somewhere. in this case, however, turbo
// handles the disabled attribute of the submitter.
}
});
}

0 comments on commit 30ce337

Please sign in to comment.