简体   繁体   中英

Event.preventDefault() not working, form submitted twice

I have two pages, both forms are basically the same, with the stripe element, but one has extra fields and the other does not.

The form with extra fields event.preventDefault() does not seem to stop the form submit, so the form gets submitted twice, but one without extra fields does not.

Why is one form isTrusted === true and the other isTrusted === false ? What controls this?

Could this be the cause of the preventDefault() not working?

After more testing, I found that:

<%= form_tag add_card_path(@product.id), id: "payment-form" do

does not submit twice, but

<%= form_with add_card_path(@product.id), id: "payment-form" do 

does submit twice, hence the preventDefault() does not work.

Why would that be?

<%= form_tag add_card_path(@product.id), id: "payment-form" do %>
  <div class="form-row">
    <div id="card-errors" role="alert" class="col"></div>
  </div>
  <div class="form-row">
    <div id="card-element" class="col"></div>
  </div>
  <div class="form-row mt-3">
    <button class="btn_spinner col btn md-width-auto btn-primary">Add Card</button>
  </div>
<% end %>

Javascript:

// Handle form submission.
var form = document.getElementById(thatInstance.formId);
form.addEventListener('submit', function (event) {
  event.preventDefault();
  debugger;
  thatInstance.createStripeToken();
});

Inspecting Event Object from Debugger:

Working Page:

Event Object:

bubbles: true
cancelBubble: false
cancelable: true
composed: false
currentTarget: <form id="payment-form">
defaultPrevented: true
eventPhase: 2
isTrusted: false
returnValue: false
srcElement: <form id="payment-form">
target: <form id="payment-form">
timeStamp: 20826
type: "submit"

Non Working Page:

Event Object:

bubbles: true
cancelBubble: false
cancelable: true
composed: false
currentTarget: <form id="payment-form">
defaultPrevented: true
eventPhase: 2
isTrusted: true
returnValue: false
srcElement: <form id="payment-form">
target: <form id="payment-form">
timeStamp: 23652
type: "submit"

Solution:

Needed data-remote === false , not sure why.

Form_with has data-remote === true , while form_tag has data-remote === false .

From MDN about Event.isTrusted :

The isTrusted read-only property of the Event interface is a Boolean that is true when the event was generated by a user action, and false when the event was created or modified by a script or dispatched via EventTarget.dispatchEvent() .

From MDN about Event.preventDefault() :

Calling preventDefault() for a non-cancelable event, such as one dispatched via EventTarget.dispatchEvent() , without specifying cancelable: true has no effect.

In Rails form_with() and form_tag() operate differently.

According to this article:

https://m.patrikonrails.com/rails-5-1s-form-with-vs-old-form-helpers-3a5f72a8c78a

"All forms generated by form_with will be submitted by an XHR (Ajax) request by default. There is no need to specify remote: true as you have to with form_tag and form_for."

Hence, either turning remote to false (local: true) or using form_tag solved the issue, as .preventDefault stops the local submit, not ajax submits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM