FormData() 对象不添加来自表单的提交类型输入,而在 Firefox 上

问题描述 投票:0回答:4

今天我遇到了一个有趣的错误,花了很多时间才弄清楚。

设置

页面上的表格。提交时,数据将被捕获并使用它创建

new FormData()
对象。

该对象随

xhr
请求一起发送到
.php
脚本,然后返回
ok
/
error
消息。

代码看起来像这样:(简化版本,不需要绒毛

<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>

将此发送到

.php
将产生一个如下所示的数组:

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

.php
会用
{"message":"ok","code":0}
{"message":"error","code":1}

回应

现在这是预期的行为。这是我在 Chrome、IE 或 Safari 上得到的。

问题

然而,在 Firefox 上,除了没有

submit
输入 (
name="send"
) 键/值对外,我得到相同的数组:

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

我在 Linux 和 Windows 上都尝试过,以覆盖我的基础,但它仍然给出了同样令人不满意的结果。

解决方案

在网上搜索并一无所获之后,我解决它的方法(更多的是修补,而不是真正解决)是覆盖

send
键/值:

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

这行得通,因为如果它已经被定义(Chrome,等等......)它会被覆盖,如果它不存在,它就会被创建。

问题

  1. 相似 - 你遇到过相似的事情吗?
  2. Fix - 我认为我的解决方案是 hack,你有更好的修复方法吗?
javascript forms firefox xmlhttprequest form-data
4个回答
12
投票

FireFox 似乎是正确的,根据 WHATWG 规范。

XMLHttpRequest
FormData
构造函数的规范说:

  1. 如果给出
    form
    ,将
    fd
    的条目设置为构造的结果 form
    .
    的表单数据集

然后在构建表单数据集的描述中说:

在提交者提交者的上下文中,为表单form构建表单数据集的算法如下所示。如果没有另外指定,submitter 为空。

表单中的按钮只有在它是提交者时才会包含在表单数据集中。但是当从

FormData
构造函数执行此算法时,没有指定提交者,因此表单数据集中不应包含任何按钮。


3
投票

在 Chrome 58 中遇到类似的事情。

在我的问题中,有多个提交按钮,我需要知道选择了哪一个,或者至少是否选择了特定的按钮。

我可怕的 hack 是显式监听被选中的按钮,创建一个隐藏的输入并将其插入提交按钮之前。

更新:改进的 hack

监听提交按钮的点击并作为提交者通过按钮发送到 on('submit'),并在 ajax 调用中使用它之前附加到 FormData 对象。

修改以适应输入 [type="submit"] 的口味,并且可能对

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);
    }
    ...
});

原创黑客

$('#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');
});

不幸的是,在我的委托表格处理程序中没有发起人信息

$('#defaultModalObject-1').on('submit', 'form', function(event) { ... });


1
投票

我们在 linux 客户端上有同样的问题,使用下面的代码将所有按钮元素添加到我们的表单数据中。

第一个问题是在某些条件下获取表单数据时出错

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

第二个问题类似于以ajax形式添加按钮的问题。有时我们在一种形式中有多个按钮,并且想要检测按下了哪个按钮。

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

如果有人需要使用输入类型提交可以添加像上面的代码,我们在这种情况下使用按钮:)


0
投票

规范已更新以支持

submitter
传递给
FormData
,并且功能在最新版本的主要浏览器(ChromeFirefoxSafari)中可用。对于不支持的浏览器,您可以使用 formdata-submitter-polyfill 包。这样你就可以可靠地创建
FormData
对象来匹配等效的原生表单提交(即包括提交按钮的条目,如果合适的话)。

提交处理程序中的基本用法如下所示:

myform.addEventListener("submit", (e) => {
  e.preventDefault();
  const formData = new FormData(e.target, e.submitter);
  // do something with formData...
});

根据您的目标浏览器版本,您可能还想使用 event-submitter-polyfill 包,它确保

submitter
属性设置在
SubmitEvent
.

© www.soinside.com 2019 - 2024. All rights reserved.