Tips for successfully implementing event handlers when using JavaScript's .submit() method on a form

EDITOR'S NOTE: As I was writing out the problem, I actually managed to find a solution. However, I decided to still post it here in case it might be helpful to someone else (as my brief search on Stack Overflow didn't show anyone asking exactly the same question).


I have a form with a web component that is controlled by JavaScript, structured like this:

<form id="myform">
  <input type="text" value="example" tabindex="1" />
  <web-component tabindex="2"></web-component>
  <input type="submit" tabindex="3" />
</form>

<script>
let form = document.getElementById('myform');

form.addEventListener('submit' (e) => {
  e.preventDefault();

  console.log('Form is posting');

  // Handle form logic here
})
</script>

In the web component, I want the form to be 'submitted' when tabbing to the web component and pressing 'enter'. For this purpose, I added the following event handler within the web component:

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.submit();
    })
  }
}

The issue arises because form.submit() submits the form without triggering an event that can be monitored. This causes the form event handler not to execute, resulting in the form being posted without any JavaScript validation. One approach to address this would involve changing the form submit function to a named function as follows:

form.addEventListener('submit', handleFormSubmission);

myComponent.addEventListener('keydown', (e) => {
  if(e.code === 'Enter') handleFormSubmission();
})

However, this solution limits the usability of the web component across multiple forms, making it less readable. Another option is to search for an input[type=submit] or button[type=submit] within the form and trigger a click on it, but that seems cumbersome.

After further investigation, I discovered the use of dispatchEvent, which fires a custom event instead of just calling submit():

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.dispatchEvent(new Event('submit'));
    })
  }
}

Although close to a solution, I encountered a challenge where e.preventDefault() was not respected, meaning that JS validation couldn't halt the submission. Delving deeper into the specifications, I learned that the Event constructor accepts additional settings, such as

{bubbles: true, cancelable: true}
. This final tweak made it work smoothly:

let form = document.getElementById('myform');

form.addEventListener('submit' (e) => {
  e.preventDefault();

  console.log('Form is posting');

  // Handle form logic here
});

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.dispatchEvent(new Event('submit', {cancelable: true}));
    })
  }
}

Answer №1

To be clear, the recommended solution is to utilize the dispatchEvent method in order to generate a fresh Event and specify cancelable as true instead of relying on the .submit() function.

For instance:

let form = document.getElementById('myform');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  console.log('Form is submitting');

  // Implement form processing here
});

class CustomComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') {
        form.dispatchEvent(new Event('submit', { cancelable: true }));
      }
    })
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Sequelize to Convert and Cast Data in iLike Queries

When using Sequelize for a full-text search, I encountered an issue with applying the iLike operator to columns of INTEGER or DATE type. How can I cast off a column in this case? To illustrate, here is an example of what I am trying to achieve with a Post ...

Angular Resolution Verification

I'm currently working on making HTTP calls in Angular and I want to trigger a different service function if an error occurs. The problem is, no matter what the original service call function returns, the promise always ends up being "undefined". Here& ...

Issue with Socket.io connection event failing to trigger

Having recently delved into the world of socket.io, I followed the provided documentation and watched several tutorials on YouTube to set up a basic functionality. My goal was to see "New socket connection" logged in the console when I visit the index page ...

Creating a Dynamic Counter for Real-Time Message Updates in a Personal Messaging Application with jQuery

I am currently in the process of developing a Personal Message System for my website. My goal is to have the number of new messages in each chat displayed and updated in real-time, just like the red "box" showcased in the screenshot below: https://i.sstati ...

My child template in Angular UI is not loading properly due to the presence of multiple views when the URL changes

After reviewing a couple of questions similar to this on various forums, I may have overlooked a crucial detail in them. Upon loading http://localhost:8000/characters/#/mages/detail/3, I am being redirected to my 'otherwise' URL: $urlRouterProvi ...

Issue encountered while retrieving value from asynchronous dns.lookup() function

I am currently in the process of developing a function that validates a url by utilizing the dns.lookup() function, which is outlined below: const dns = require('dns'); const verifyURL = (url) => { const protocolRegEx = /^https?:\/& ...

invoke a managed bean to execute JavaScript code

I am facing an issue while trying to clear a hidden form value in a JSF page from a managed bean class. I tried calling a method where I used the following code snippet to call JavaScript, but unfortunately it throws a java.lang.NullPointerException. The c ...

Hide the scrollbar in the div depending on the specified condition

I'm having trouble with this particular process and haven't been successful so far... I currently have a customized scrollbar within a div element, and what I am attempting to do is remove the scrollbar when the height of the div is less than 19 ...

Boot up 4 collapse feature to conveniently close all other collapsible items at once

Utilizing the Bootstrap 4 Collapse component. My goal is to toggle between collapsible sections like "Categories" and "Brands", displaying only one at a time. The current issue is that multiple collapsible elements are visible simultaneously. .view-cust ...

The act of transmitting data via a timer using JS WebRTC leads to crashes if the page is reloaded before

In one of my server.js files served by a node, I have written the following code snippet: function multiStep(myConnection, data) { var i=0; var myTimer=setInterval(function() { if (i<data.length){ var element=JSON.string ...

I can't seem to figure out why the removeChild() function is not functioning properly in my

Recently, I've been working on a search website where users can input either a partial or full name and then click a button to display a list of actors whose names contain that specific string in a hint-like fashion. These names are sourced from a MyS ...

Guide on redirecting the user to the "notFound" page within the getServerSideProps function in Next.JS whenever an incorrect params.id is provided

export const getServerSideProps = async ({ params }) => { const res = await fetch( `https://pixabay.com/api/?key=${process.env.API_KEY}&id=${params.id}` ); const { hits } = await res.json(); if (!hits) { return { notFound: tr ...

Problem with JavaScript regular expressions and enumeration

Hello there! I'm facing a challenge on how to transform my text using ul and li tags. Let me explain: let text = "You are the best person"; I want to change the "the best person" part into: <ul> <li>the</li> <li>b ...

Could you explain the contrast among "yarn serve," "yarn start," and "yarn build"?

Although both "yarn serve" and "yarn start" can launch my Vue project, I'm unsure of the differences between them. I've heard that "yarn build" is for packaging, but why don't I use it at work? Usually, I just upload my code to git and let ...

Flask fails to recognize JSON data when transmitted from Nodejs

I am encountering an issue when trying to send JSON data from Node to Flask. I am having trouble reading the data in Flask as expected. Despite attempting to print request.data in Flask, no output is being displayed. Additionally, when I tried printing req ...

How can you retrieve a value in NodeJS Promise (Q) even when the promise fails?

As I dive into the world of promises in my NodeJS projects, I encountered a challenging situation. Despite reading the Promises/A+ spec and conducting extensive searches online, I struggled to find an elegant solution for accessing a value generated within ...

Hermes js engine encounters a TypeError when attempting to access the property '__expo_module_name__' of an undefined value

After updating my expo and react native app to the latest version, I encountered a problem that I couldn't find a solution for despite searching on Google. Link to image ...

False return - Inoperative link - Scroll option

I have a JavaScript drop-down menu that is functioning correctly, but when I click on one of the links in the dropdown, the link does not work. I suspect it has something to do with my "return false/true" setup. Here's my JavaScript code: function d ...

"Exploring the symbiotic relationship between Node.js and Express.js: an

I recently started learning Node.js and Express.js. I used the Express.js executable (express) to create an express application, which generated the following lines in app.js: ... var app = express(); http.createServer(app).listen(app.get('port' ...

Exploring the getInitialProps function in NextJS

I'm currently exploring NextJS and came across a sample page implementation: class IndexPage extends Component { static async getInitialProps(context) { return {}; } render() { return <div>hello world</div>; } } export def ...