Skip to content

Commit e31a5ff

Browse files
committed
Ensure that bound events are cleared for form validation controller after submit or navigation away
1 parent 7c2ba10 commit e31a5ff

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

app/javascript/controllers/better_together/form_validation_controller.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ export default class extends Controller {
66

77
connect() {
88
this.element.setAttribute("novalidate", true); // Disable default HTML5 validation
9-
this.element.addEventListener("input", this.checkValidity.bind(this));
9+
// Cache bound handlers so we can remove them on disconnect
10+
this._onInput = this.checkValidity.bind(this);
11+
this._onChange = this.markFieldAsDirty.bind(this);
12+
this._onSubmit = this.handleFormSubmit.bind(this);
13+
this._onSubmitEnd = this.handleSubmitEnd.bind(this);
14+
this._onBeforeVisit = this.handleTurboNavigation.bind(this);
15+
16+
this.element.addEventListener("input", this._onInput);
1017

1118
this.isSubmitting = false; // Track form submission
1219
this.originalValues = new Map(); // Store initial field values
@@ -16,19 +23,23 @@ export default class extends Controller {
1623
this.storeInitialValues();
1724

1825
// Listen for changes to mark fields dirty
19-
this.element.addEventListener("change", this.markFieldAsDirty.bind(this));
26+
this.element.addEventListener("change", this._onChange);
2027

2128
// Handle form submission
22-
this.element.addEventListener("submit", this.handleFormSubmit.bind(this));
23-
this.element.addEventListener("turbo:submit-end", this.handleSubmitEnd.bind(this));
29+
this.element.addEventListener("submit", this._onSubmit);
30+
this.element.addEventListener("turbo:submit-end", this._onSubmitEnd);
2431

2532
// Handle Turbo navigation (unsaved changes warning)
26-
document.addEventListener("turbo:before-visit", this.handleTurboNavigation.bind(this));
33+
document.addEventListener("turbo:before-visit", this._onBeforeVisit);
2734
}
2835

2936
disconnect() {
30-
document.removeEventListener("turbo:before-visit", this.handleTurboNavigation.bind(this));
31-
this.element.removeEventListener("turbo:submit-end", this.handleSubmitEnd.bind(this));
37+
// Remove all listeners using the cached handler references
38+
if (this._onBeforeVisit) document.removeEventListener("turbo:before-visit", this._onBeforeVisit);
39+
if (this._onSubmitEnd) this.element.removeEventListener("turbo:submit-end", this._onSubmitEnd);
40+
if (this._onSubmit) this.element.removeEventListener("submit", this._onSubmit);
41+
if (this._onChange) this.element.removeEventListener("change", this._onChange);
42+
if (this._onInput) this.element.removeEventListener("input", this._onInput);
3243
}
3344

3445
storeInitialValues() {
@@ -59,6 +70,7 @@ export default class extends Controller {
5970
return;
6071
}
6172

73+
// Prevent unsaved-changes prompt during form-driven navigation
6274
this.isSubmitting = true;
6375
}
6476

0 commit comments

Comments
 (0)