表单仍然提交,尽管使用了preventDefault(),因为存在不同的EventListener。

huangapple go评论126阅读模式
英文:

Form submits despite preventDefault() because of a different EventListener

问题

我有两个事件监听器,一个用于处理表单,另一个用于“添加到购物车”按钮。当事件触发时,会向服务器发送一个POST请求,服务器会处理相应的数据,因此我需要表单不被提交,而是由服务器处理。

在实现处理“添加到购物车”按钮的事件监听器之前,使用event.preventDefault();时,表单正常工作。然而,使用按钮的事件监听器后,表单现在提交并将我重定向到/login。我尝试了我找到的每个解决方案,包括使用.stopPropagation().preventDefault()return=false;在两个监听器上,将按钮更改为div元素。但是,除非我完全删除第二个事件监听器,否则表单不会按预期工作。

我可以替换表单元素为div,但它必须保持为HTML表单,因此我必须解决这个问题。

以下是代码,提前感谢:

window.onload = function formSubmit() {
  const form = document.getElementById('login-form');
  form.addEventListener('submit', event => {
    event.preventDefault(); // 防止表单提交
    const username = form.elements.username.value;
    const password = form.elements.password.value;
    login(username, password);
  });
}

// addbuttons是在其他元素加载后动态添加的,所以我在查询选择器中设置了一个超时来收集它们
setTimeout(window.onload = function productRequest() {
  const purchaseBtns = document.querySelectorAll('.purchase-button');

  purchaseBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      var product_selected;
      for (i in products) {
        if (products[i].id == btn.dataset.productId) {
          product_selected = products[i];
        }
      }
      addToCart(product_selected);
    });
  });
}, 1000);
英文:

I have two EventListeners, one to handle a form and the other for 'Add to Cart' buttons. When the events are fired, a post request is sent to the server which handles the according data, so i need the form to not be submitted but be handled by the server instead.

Before implementing the EventListeners which handles the 'Add to cart' buttons, the form was working as intended with the use of event.preventDefault();. With the buttons' EventListener however the form now submits and directs me to /login. I have tried every solution I found, I used .stopPropagation(), .preventDefault() and return=false; to both listeners, I changed the buttons to div elements. However the form is not working as intended unless I completely remove the second EventListener.

I would go on replacing the form element with a div but it needs to stay as an HTML form, so I have to work out a solution to this.

I'm including the code below, thanks in advance:

window.onload =function formSubmit(){
  const form = document.getElementById('login-form');
  form.addEventListener('submit', event => {
    
    event.preventDefault(); // prevent the form from submitting
    const username = form.elements.username.value;
    const password = form.elements.password.value;
    login(username, password);
      
  });
}

//addbuttons are added dynamically after the other elements are already loaded so im putting a timeout for queryselector to gather them
setTimeout(window.onload =function productRequest(){
  const purchaseBtns = document.querySelectorAll('.purchase-button');

  purchaseBtns.forEach((btn) =>{
      btn.addEventListener('click', () => {
      var product_selected;
      for(i in products){
        if(products[i].id == btn.dataset.productId){
          product_selected = products[i];
        }
      }
      addToCart(product_selected);

    });
    
  });
  
}, 1000);

答案1

得分: 2

window.onload 只能存储一个函数...不能再多了。

看起来第一个会触发...而不是第二个,因为在那时,load 事件已经触发(在第二次分配之前覆盖了第一个,即在第一个超时之后)。

所以尝试使用一个 load 事件监听器:

document.addEventListener("load", function(){

  // 表单的事件监听器
  const form = document.getElementById('login-form');
  form.addEventListener('submit', event => {

    event.preventDefault(); // 阻止表单提交
    const username = form.elements.username.value;
    const password = form.elements.password.value;
    login(username, password);
  });


  // 按钮事件监听器在页面加载后设置 1 秒
  setTimeout(() => {
    const purchaseBtns = document.querySelectorAll('.purchase-button');
    purchaseBtns.forEach((btn) =>{
      btn.addEventListener('click', (event) => {

        // 阻止事件冒泡到表单,如果按钮在其中
        event.stopPropagation()

        // 并且显然,也要防止提交
        event.preventDefault();

        var product_selected;
        for(i in products){ // 希望您已经定义了这些产品...
          if(products[i].id == btn.dataset.productId){
            product_selected = products[i];
          }
        }
        addToCart(product_selected);
      });
    });
  }, 1000)

})  // 结束加载事件处理程序
英文:

window.onload can store ONE function... No more.

Seems like the first one fires... And not the second because at that point, the load event already fired (before the second assignement overwrote the first, that is after the first timeout).

So try with one load event listener:

document.addEventListener("load", function(){
  
  // Form's event listener
  const form = document.getElementById('login-form');
  form.addEventListener('submit', event => {
    
    event.preventDefault(); // prevent the form from submitting
    const username = form.elements.username.value;
    const password = form.elements.password.value;
    login(username, password);
  });
  
  
  // Buttons event listeners setting 1 second after page load
  setTimeout(() => {
    const purchaseBtns = document.querySelectorAll('.purchase-button');
    purchaseBtns.forEach((btn) =>{
      btn.addEventListener('click', (event) => {
      
        // Prevent the event from bubbling to the form if the buttons are inside it
        event.stopPropagation()

        // and obviously, also prevent submit
        event.preventDefault();
        
        var product_selected;
        for(i in products){ // Hoping you have that products defined...
          if(products[i].id == btn.dataset.productId){
            product_selected = products[i];
          }
        }
        addToCart(product_selected);
      });
    });
  }, 1000)
  
})  // end of the load event handler

huangapple
  • 本文由 发表于 2023年1月9日 08:09:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定