The FormData () object does not add input like input from the form, but in Firefox

Today I stumbled upon an interesting mistake that took a long time to get to the bottom.

Customization

The form on the page. When new FormData() , data is captured, and a new FormData() object is created with it.

This object is sent with an xhr and xhr request to a .php script, which then returns an ok / error message.

The code looks something like this: (simplified version, without the need for fluff)

 <form name="frm" id="frm" action="" method="post" onsubmit="save(event, this);" enctype="multipart/form-data"> <input name="name" id="name" type="text" value="..." /> <input name="email" id="email" type="text" value="..." /> <input name="phone" id="phone" type="text" value="..." /> <input name="website" id="website" type="text" value="..." /> <textarea name="details" id="details"></textarea> <input name="send" type="submit" value="Send" /> </form> <script type="text/javascript"> function save(e, frm) { if (document.getElementById('nume').value == '' || document.getElementById('email').value == '' || document.getElementById('telefon').value == '' || document.getElementById('site').value == '') { alert('Forms empty'); } else { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { var r = JSON.parse(xhr.responseText); if (r.code == 0) { document.getElementById('message_ok').style.display = 'block'; } else { document.getElementById('message_err').style.display = 'block'; } } }; xhr.open('POST', 'http://url', true); var data = new FormData(frm); xhr.send(data); } e.preventDefault(); } </script> 

Sending this message to .php will cause the array to look like this:

 Array ( [name] => some name [email] => some email [phone] => 11111111 [website] => some site [details] => some details [send] => Send ) 

and .php will respond either {"message":"ok","code":0} , or {"message":"error","code":1}

Now this is the expected behavior. This is what I get from Chrome, IE or Safari.

Problem

In Firefox, however, I get the same array, except for a pair of submit input ( name="send" ) 2>:

 Array ( [name] => some name [email] => some email [phone] => 11111111 [website] => some site [details] => some details ) 

I tried on both Linux and Windows to cover my base, but it still gave the same unsatisfactory result.

Decision

After searching the Internet and the appearance of an empty path, as I decided (more fixes, not solutions), I had to rewrite the send key / value:

 var data = new FormData(frm); data.append('send', 'Send'); xhr.send(data); 

This works because if it is already defined (Chrome, etc.), it is overwritten, if it does not exist, it is created.

Questions

  • Similar . Have you ever come across something similar?
  • To fix . I believe my decision is hacked, do you have any ideas for a better fix?
+6
source share
3 answers

FireFox seems correct according to the WHATWG specification.

The XMLHttpRequest specification of the FormData constructor says:

  1. If form is given, set the fd entries to the result of building the data form for the form .

Then the description of the construction of the form dataset says:

The algorithm to build a form dataset for the form form, optionally in the context of the applicant, is as follows. Unless otherwise specified, the sender is null.

A button in a form is included only in the form data set, if it is the sender. But when this algorithm is executed from the FormData constructor, no applicants are specified, so no buttons should be included in the form dataset.

+4
source

Facing a similar thing in Chrome 58.

There are several submit buttons in my problem, and I need to know which one is selected, or at least if a specific one is selected.

My terrible hack is to explicitly listen to the selected button, create a hidden input and paste it in front of the submit button.

Updated: Improved Hack

Listen to the clicks of the submit buttons and send via the button as the sender to on ('submit') and add a FormData object before using it in an ajax call.

Change the taste for typing [type = "submit"] and, possibly, additional error checking in the content of the submitter .

 $('#defaultModalObject-1').on('click', 'button[type="submit"]', function(event) { /* horrible hack to detect wizard_goto_step submissions via ajax */ event.preventDefault(); $(event.target.form).trigger('submit', event.target); }); $('#defaultModalObject-1').on('submit', 'form', function(event, submitter){ ... var formdata = new FormData(form[0]); if (submitter != undefined) { formdata.append(submitter.name, submitter.value); } ... }); 

Original hack

 $('#ajax_form_modal_result').on('click', 'button[type="submit"][name="wizard_goto_step"]', function(event) { /* horrible hack to detect wizard_goto_step submissions via ajax */ event.preventDefault(); var input = $('input[type="hidden"]').attr('name', 'wizard_goto_step').val(event.target.value); $(event.target).before(input); $(event.target.form).trigger('submit'); }); 

Unfortunately, the sender information is not available in my delegated form handler $('#defaultModalObject-1').on('submit', 'form', function(event) { ... });

+1
source

We have the same problem for linux clients and using the below code to add all button elements to our forms.

The first problem is an error while receiving form data in some codes

 if($this.is('form')) { var fd = new FormData($this.get(0)); } else { var fd = new FormData(); } 

The second issue is similar to the question of adding a button in an ajax form. sometimes we have more buttons in one form and you want to determine which one is pressed.

 $this.find('button').each(function() { fd.append(this.getAttribute('name'), this.value); }); 

If someone needs to use an input type that can be added, for example, the code above, we use the button in the following conditions :)

0
source

All Articles