IE не отправляет динамически добавленные элементы формы

Я написал некоторый 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 был доволен?)


person Jeremy Frank    schedule 04.03.2009    source источник


Ответы (3)


Это ошибка IE?

Кажется, так. Когда вы создаете элемент ‹input> с помощью методов 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 или другие настраиваемые свойства, которые вы прикрепили к каждому дочернему элементу. Кроме того, ненужный цикл сериализации / синтаксического анализа выполняется медленно.

person bobince    schedule 04.03.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';
person levik    schedule 04.03.2009
comment
+1 при избегании setAttribute. -1 при вызове createElement-with-markup, что является вопиюще уродливым взломом, предназначенным только для IE. - person bobince; 04.03.2009
comment
Я согласен с тем, что это взлом, поэтому я предлагаю плакату сначала попробовать установить свойства. Если это не сработает, я не вижу другого способа осуществить то, что он хочет. - person levik; 04.03.2009

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

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

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

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

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

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

Ура,
--jsf

person Jeremy Frank    schedule 04.03.2009
comment
Я добавляю несколько элементов через document.createElement, и каждый элемент имеет несколько атрибутов. Один из атрибутов является идентификатором. У меня также есть функция javascipt на той же странице, которая получает идентификатор через document.getElementById (ID) и innerHTML. Как мне сослаться или получить правильный элемент на основе идентификатора динамически созданного элемента? Я использую IE 8 .. работает в Firefox :) - person Jim; 18.11.2011