You are passing the event
parameter when attaching the submitStep
function, which at that point is undefined
.
You would need to rearrange arguments of the submitStep
so that event would be the last argument, then partially apply stepNo
and trigger
using .bind()
.
But there’s another bug in your code. You are trying to remove event listener of the submitStep
inside of it, which will not work after calling .bind()
, as .bind()
returns a new function. I would separate the event registration into a separate function, which would make a wrapper around the event handler and register the wrapper as the handler. Then during execution it would call the actual handler and unregister itself.
const addEventListenerOnce = (trigger, eventName, handler) => {
// Create a function that will be registered as event handler
const handlerWrapper = (event) => {
// Call the actual handler
handler(event);
// Remove the registered wrapper
trigger.removeEventListener(eventName, handlerWrapper);
};
// Register the wrapping function as event listener
trigger.addEventListener(eventName, handlerWrapper);
};
const submitStep = (stepNo, event) => {
event.preventDefault();
toggleStep(stepNo);
}
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
// Only stepNo is applied, event is left
// Function signature would be then (event) => void
const submitHandler = submitStep.bind(null, 4);
// Register the submit handler to be called once
addEventListenerOnce(trigger, 'submit', submitHandler);
}
I have some HTML forms on the same page that are toggled sequentially one after another, after the previous one has been submitted. The user is able to navigate back and forth between them, so I need to remove submit event listeners after they have been triggered, so I can reattach them again if needed.
I am currently attaching submit event handlers inside the “rendering process” for each one of them, removing the event handler after executing the function like this:
form.addEventListener('submit', submitStepOne)
function submitStepOne(e) {
e.preventDefault()
sendData()
form.removeEventListener('submit', submitStepOne)
}
same code for multiple form elements (submitStepTwo
, submitStepThree
…)
Because I don’t want to keep repeating the same code, I want to create a global “submit step and go to next one” function, which I thought could look something like this:
const submitStep = (event, stepNo, trigger) => {
event.preventDefault()
toggleStep(stepNo)
trigger.removeEventListener('submit', submitStep)
}
I thought I could attach the event handler to the submit button like this, using .bind()
(tip from https://stackoverflow.com/a/23024673/10727821):
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
trigger.addEventListener('submit', submitStep.bind(null, event, 4, trigger))
}
PAGES
is an object containing the DOM element for each of the steps as well as corresponding functions for each page. PAGES.stepX.functions()
is called each time a step is toggled with toggleStep(step)
.
However, I’m getting an Uncaught TypeError: Cannot read property 'preventDefault' of undefined
. How could I rewrite the function so I can properly pass parameters to it?
Thankful for any hints!
brilliant, thank you so much! perfectly explained as well.