IE не отправляет динамически добавленные элементы формы - PullRequest
9 голосов
/ 04 марта 2009

Я написал немного 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, нажмите Submit, посмотрите, что в адресной строке. Если вы раскомментируете последнюю строку в add(), IE внезапно прекратит сообщать field3. В Firefox он работает в любом случае.

Есть идеи? Любопытный ум хочет знать. (А как мне добавить туда текст, если нужно, переносимым способом, чтобы IE был доволен?)

Ответы [ 3 ]

7 голосов
/ 04 марта 2009

Это ошибка IE?

Кажется, так. Когда вы создаете элемент с помощью методов DOM, IE не совсем подхватывает атрибут «name». Это что-то вроде того, что элемент отправляется, но если вы попытаетесь получить «innerHTML» представление элемента, он загадочным образом исчезнет. Этого не произойдет, если вы создадите элемент, написав напрямую в innerHTML.

Также, если вы используете методы навигации формы DOM уровня 0, такие как «myform.elements.x.value», доступ через массив «elements» может не работать (аналогично прямой доступ к «myform.x», который некоторые люди ошибочно используют) , В любом случае в наши дни вы можете предпочесть getElementById ().

Итак либо использовать innerHTML или использовать методы DOM; Лучше не смешивать их при создании полей формы.

Это задокументировано (см. "Замечания") и, наконец, исправлено в IE8.

В любом случае, никогда не делайте:

div.innerHTML + = '...';

Это только синтаксический сахар для:

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

Другими словами, он должен сериализовать все дочернее HTML-содержимое элемента, затем выполнить конкатенацию строк, а затем повторно проанализировать новую строку обратно в элемент, отбросив весь исходный контент. Это означает, что вы потеряете все, что не может быть сериализовано: а также поддельные атрибуты «name», созданные в IE, которые также означают любые обработчики событий JavaScript, прослушиватели DOM или другие пользовательские свойства, которые вы прикрепили к каждому дочернему элементу. Кроме того, ненужный цикл сериализации / анализа является медленным.

3 голосов
/ 04 марта 2009

Спасибо Бобинсу и Левику за ваши ответы. Используя эти и еще несколько экспериментов, вот мои выводы:

  1. Да, это ошибка IE.

  2. IE 8 исправляет ошибку в соответствии с Microsoft : «Internet Explorer 8 и более поздние версии могут устанавливать атрибут NAME во время выполнения для элементов, динамически создаваемых с помощью метода createElement.»

  3. Ошибка заключается в следующем: вызов e.setAttribute("name", "field3") only kind-of устанавливает имя. Это будет работать, если с элементом ничего не происходит, но если запрошено сериализовать, имя не сериализуется. Поэтому, когда я сказал innerHTML += " ", это вызвало сериализацию, которая потеряла имя, поэтому оно не было восстановлено после десериализации. Без имени, без включения в отправку формы.

  4. Обходной путь # 1: e = document.createElement("<input name='field3' />") сработает, даже если столкнется с сериализацией.

  5. Обходной путь № 2: Вместо добавления текста с помощью innerHTML + =, я могу добавить текстовый элемент, например так: div.appendChild(document.createTextNode(" "));. Я подумал, что должен быть лучший способ добавления текста, и теперь я знаю это: -).

Приветствия,
--jsf

3 голосов
/ 04 марта 2009

IE очень требователен к изменению некоторых встроенных свойств во время выполнения. Например, имя элемента ввода не может быть изменено во время установки.

На твоем месте я бы попробовал две вещи:

  1. Вместо использования setAttribute() попробуйте явно установить свойства name, type и value:

    e.name = "text";

  2. Если это не сработает, возможно, вам придется включить все эти атрибуты в вызов document.createElement():

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

    это может вызвать исключение в некоторых браузерах. Так что лучший кросс-браузерный способ будет:

.

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