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

时间:2009-03-04 18:50:15

标签: javascript internet-explorer webforms dhtml

我编写了一些JavaScript来允许编辑HTML表单中的项目列表,包括添加和删除项目。它在Firefox中运行。在Internet Explorer中尝试时,我发现任何添加的项目都没有与表单一起提交。

长话短说......大量的简化,调试,找出触发IE忽略新表单输入的行。所以行为问题就解决了。

但现在我必须问:为什么?这是IE漏洞吗?

以下是简化代码:

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

要尝试一下,做一下显而易见的事情:在IE中加载,单击“添加”,单击“提交”,查看地址栏中的内容。如果您取消注释add()中的最后一行,IE将突然停止报告field3。它在Firefox中都可以正常工作。

有什么想法吗?一个好奇的头脑想要知道。 (如果需要,我将如何以便携方式添加文本,因此IE很高兴?)

3 个答案:

答案 0 :(得分:7)

  

这是IE漏洞吗?

似乎是这样。当您创建&lt; input&gt;时通过DOM方法的元素,IE并没有完全拿起'name'属性。元素确实提交了,但是如果你试图获得元素的'innerHTML'表示,它就会神秘地消失。如果通过直接写入innerHTML来创建元素,则不会发生这种情况。

此外,如果您使用DOM Level 0表单导航方法,例如'myform.elements.x.value',则通过'elements'数组访问可能不起作用(类似直接'myform.x'访问某些人误导使用) 。在任何情况下,您可能更喜欢getElementById()。

所以 使用innerHTML 使用DOM方法;最好不要在创建表单字段时混合它们。

这是documented (see ‘Remarks’),最后在IE8中修复。

无论如何,永远不要这样做:

  

div.innerHTML + ='...';

这只是语法糖:

  

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

换句话说,它必须序列化元素的整个子HTML内容,然后执行字符串连接,然后将新字符串重新解析回元素,丢弃所有原始内容。这意味着你丢失了任何无法序列化的东西:以及IE伪造的半创建'name'属性,这也意味着任何JavaScript事件处理程序,DOM Listeners或你附加到每个子元素的其他自定义属性。此外,不必要的序列化/解析周期很慢。

答案 1 :(得分:3)

IE在运行时更改某些内置属性非常挑剔。例如,设置时无法更改输入元素的名称。

如果我是你,我会尝试两件事:

  1. 请尝试明确设置setAttribute()nametype属性,而不是使用value

    e.name = "text";

  2. 如果这不起作用,您可能必须将所有这些属性包含在document.createElement()调用中:

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

    这实际上可能会在某些浏览器中引发异常。所以最好的跨浏览器方式是:

  3. 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';
    

答案 2 :(得分:3)

谢谢bobince和levik的答案。使用这些,以及一些更多的实验,这是我的结论:

  1. 是的,这是一个IE错误。

  2. IE 8根据Microsoft修复了错误:“Internet Explorer 8及更高版本可以在运行时在使用createElement方法动态创建的元素上设置NAME属性。”

  3. 错误是这样的:只调用e.setAttribute("name", "field3") kind-of 设置名称。如果元素没有其他任何内容,它将起作用,但如果请求序列化,则名称不会序列化。所以,当我说innerHTML += " "强制序列化时,它失去了名字,因此在反序列化时没有恢复。没有名字,也没有包含在表格提交中。

  4. 解决方法#1:e = document.createElement("<input name='field3' />")即使在面对序列化时也能正常工作。

  5. 解决方法#2:我可以添加如下文本元素:div.appendChild(document.createTextNode(" "));,而不是使用innerHTML + =添加文本。我认为必须有更好的方法来添加文字,现在我知道了: - )。

  6. 干杯,
    --jsf