简体   繁体   English

IE 未提交动态添加的表单元素

[英]IE is not submitting dynamically added form elements

I wrote some JavaScript to allow editing a list of items within an HTML form, including adding and removing items.我写了一些 JavaScript 来允许编辑 HTML 表单中的项目列表,包括添加和删除项目。 Got it working in Firefox.让它在 Firefox 中工作。 When trying it in Internet Explorer, I found that any added items were not being submitted with the form.在 Internet Explorer 中尝试时,我发现任何添加的项目都没有与表单一起提交。

Long story short... lots of simplification, debugging, figured out what line is triggering IE to ignore the new form input.长话短说...大量的简化、调试,找出了触发 IE 忽略新表单输入的行。 So the behavior problem is solved.这样行为问题就解决了。

But now I must ask: Why?但现在我必须问:为什么? Is this an IE bug?这是一个IE错误吗?

Here is the simplified code:这是简化的代码:

<html>
<head>
    <title>Test</title>
    <script type="text/javascript">
        function add() {
            div = document.getElementById("mylist");

            // *** Adding text here works perfectly fine. ***
            div.innerHTML += " ";

            e = document.createElement("input");
            e.setAttribute("type", "text");
            e.setAttribute("name", "field3");
            e.setAttribute("value", "--NEWVALUE--");
            div.appendChild(e);

            // *** Adding text here works perfectly fine in Firefox, but for
            //     Internet Explorer it causes field3 to not be submitted. ***
            //div.innerHTML += " ";
        }
    </script>
</head>
<body>
    <form action="" method="get">
        <div id="mylist">
            <input type="text" name="field1" value="value1" />
            <input type="text" name="field2" value="value2" />
        </div>
        <a href="javascript:" onclick="add()" />Add</a>
        <input type="submit" value="Submit" />
    </form>
</body>
</html>

To try it out, do the obvious: load in IE, click Add, click Submit, look what's in the address bar.要尝试一下,做显而易见的事情:在 IE 中加载,单击添加,单击提交,查看地址栏中的内容。 If you uncomment the last line in add() , IE will suddenly stop reporting field3 .如果您取消注释add()中的最后一行,IE 将突然停止报告field3 It works fine either way in Firefox.它在 Firefox 中都可以正常工作。

Any ideas?有任何想法吗? A curious mind wants to know.好奇的心想知道。 (And how would I add text there if needed, in a portable fashion, so IE is happy?) (如果需要,我将如何以便携的方式在其中添加文本,让 IE 很高兴?)

Is this an IE bug?这是一个IE错误吗?

Seems so.似乎是这样。 When you create an <input> element through DOM methods, IE doesn't quite pick up the 'name' attribute.当您通过 DOM 方法创建 <input> 元素时,IE 并没有完全拾取 'name' 属性。 It's sort-of-there in that the element does submit, but if you try to get an 'innerHTML' representation of the element it mysteriously vanishes.元素确实提交了,但如果您尝试获取元素的“innerHTML”表示,它就会神秘地消失。 This doesn't happen if you create the element by writing directly to innerHTML.如果您通过直接写入innerHTML 创建元素,则不会发生这种情况。

Also if you use DOM Level 0 form navigation methods, like 'myform.elements.x.value', access through the 'elements' array may not work (similarly the direct 'myform.x' access some people misguidedly use).此外,如果您使用 DOM 级别 0 表单导航方法,例如“myform.elements.x.value”,则通过“元素”数组访问可能不起作用(类似于某些人错误使用的直接“myform.x”访问)。 In any case these days you might prefer getElementById().无论如何,这些天您可能更喜欢 getElementById()。

So either use innerHTML or use DOM methods;所以要么使用innerHTML ,要么使用DOM方法; best not to mix them when creating form fields.创建表单域时最好不要混合它们。

This is documented (see 'Remarks') and finally fixed in IE8.这已记录在案(请参阅“备注”)并最终在 IE8 中修复。

In any case, never do:在任何情况下,永远不要这样做:

div.innerHTML+= '...'; div.innerHTML+= '...';

This is only syntactical sugar for:这只是语法糖:

div.innerHTML= div.innerHTML+'...'; div.innerHTML= div.innerHTML+'...';

In other words it has to serialise the entire child HTML content of the element, then do the string concatenation, then re-parse the new string back into the element, throwing away all the original content.换句话说,它必须序列化元素的整个子 HTML 内容,然后进行字符串连接,然后将新字符串重新解析回元素,丢弃所有原始内容。 That means you lose anything that can't be serialised: as well as IE's bogus half-created 'name' attributes that also means any JavaScript event handlers, DOM Listeners or other custom properties you have attached to each child element.这意味着您会丢失任何无法序列化的内容:以及 IE 的虚假半创建“名称”属性,这也意味着您附加到每个子元素的任何 JavaScript 事件处理程序、DOM 侦听器或其他自定义属性。 Also, the unnecessary serialise/parse cycle is slow.此外,不必要的序列化/解析周期很慢。

IE is very picky about changing some built-in properties at runtime. IE 对在运行时更改一些内置属性非常挑剔。 For example, the name of an input element cannot be changed while set.例如,输入元素的名称在设置时不能更改。

Two things I would try if I were you:如果我是你,我会尝试两件事:

  1. Instead of using setAttribute() , try setting the name , type and value properties explicitly:尝试显式设置nametypevalue属性,而不是使用setAttribute()

    e.name = "text";

  2. If this doesn't work, you may have to include all these attributes into the document.createElement() call:如果这不起作用,您可能必须将所有这些属性包含到document.createElement()调用中:

    var e = document.createElement("<input type='text' name='field'>");

    this may actually throw an exception in some browsers.这实际上可能会在某些浏览器中引发异常。 So the best cross browser way to go would be:因此,go 的最佳跨浏览器方式是:

. .

var e;
  try {
    e = document.createElement("<input type='text' name='field'>");
  } catch (ex) {
    e = document.createElement("input");
    e.type = 'text';
    e.name = 'field';
  }
  e.value = 'value';

Thank you bobince and levik for your answers.谢谢 bobince 和 levik 的回答。 Using those, and some more experimentation, here are my conclusions:使用这些以及更多的实验,这是我的结论:

  1. Yes it is an IE bug.是的,这是一个 IE 错误。

  2. IE 8 fixes the bug according to Microsoft : "Internet Explorer 8 and later can set the NAME attribute at run time on elements dynamically created with the createElement method." IE 8 根据微软的说法修复了该错误:“Internet Explorer 8 及更高版本可以在运行时对使用 createElement 方法动态创建的元素设置 NAME 属性。”

  3. The bug is this: Calling e.setAttribute("name", "field3") only kind-of sets the name.错误是这样的:仅调用e.setAttribute("name", "field3")设置名称。 It will work if nothing else happens to the element, but if requested to serialize, the name is not serialized.如果元素没有发生任何其他事情,它将起作用,但如果请求序列化,则不会序列化名称。 So when I said innerHTML += " " that forced a serialization, which lost the name, so it was not recovered upon deserialization.因此,当我说innerHTML += " "强制进行序列化时,它会丢失名称,因此在反序列化时无法恢复。 No name, no inclusion in form submission.没有名字,没有包含在表单提交中。

  4. Workaround #1: e = document.createElement("<input name='field3' />") would work, even when faced with serialization.解决方法 #1: e = document.createElement("<input name='field3' />")会起作用,即使面对序列化也是如此。

  5. Workaround #2: Rather than adding text using innerHTML +=, I can append a text element like this: div.appendChild(document.createTextNode(" "));解决方法#2:而不是使用 innerHTML += 添加文本,我可以 append 像这样的文本元素: div.appendChild(document.createTextNode(" ")); . . I had figured there must be a better way of adding text, and now I know it:-).我认为必须有更好的添加文本的方法,现在我知道了:-)。

Cheers,干杯,
--jsf --jsf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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