Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FormData() object does not add submit-type inputs from form, while on Firefox

Today I came across an interesting bug, which took a good chunk of time to get to the bottom of.

The setup

A form on a page. On submit, the data gets captured and new FormData() object gets created with it.

That object gets sent with and xhr request to an .php script, which then returns an ok / error message.

The code looks something like this: (simplified version, no 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 to .php will result in an array which kind of looks like this:

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

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

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

The problem

On Firefox however, I get the same array except without the submit input (name="send") key/value pair:

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 basis, yet it still gave the same unsatisfying result.

Solution

After searching online and coming up empty, the way I solved it (more of patching, not really solving) was to overwrite the send key/value:

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

This works, because if it's already defined (Chrome, etc...) it gets overwritten, if it doesn't exist, it gets created.

Questions

  1. Similar - Have you ever faced something similar?
  2. Fix - I consider my solution a hack, have you got any ideas for a better fix?
like image 369
481b8423202598ecfb233c5fa68caf Avatar asked Jul 09 '16 03:07

481b8423202598ecfb233c5fa68caf


People also ask

How you can add data to FormData?

append() The append() method of the FormData interface appends a new value onto an existing key inside a FormData object, or adds the key if it does not already exist.

Can we send object in FormData?

Yes you can, you can append to formData objects.

What is new FormData ()?

The formData constructor creates and returns a new FormData object. If an HTML form element is provided, it automatically captures its fields. This parameter is optional. Additional data can be added in the FormData object using the formData. append() method.

How can I get FormData in POST request?

To post HTML form data to the server in URL-encoded format, you need to make an HTTP POST request to the server and provide the HTML form data in the body of the POST message. You also need to specify the data type using the Content-Type: application/x-www-form-urlencoded request header.


1 Answers

FireFox seems to be correct, according to the WHATWG specification.

The XMLHttpRequest specification of the FormData constructor says:

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

Then in the description of constructing the form data set, it says:

The algorithm to construct the form data set for a form form optionally in the context of a submitter submitter is as follows. If not specified otherwise, submitter is null.

A button in the form is only included in the form data set if it's the submitter. But when this algorithm is executed from the FormData constructor, no submitter is specified, so no buttons should be included in the form data set.

like image 199
Barmar Avatar answered Sep 18 '22 18:09

Barmar