Подтвердить что ты не робот

Jquery.html() странное поведение с формой

У меня есть следующий html:

<div class="copy_me_text">
    <div>
        <input type="text" name="name" />
        <input type="hidden" name="id" />
    </div>
</div>

<div class="copy_me_hidden">
    <div>
        <input type="hidden" name="name" />
        <input type="hidden" name="id" />
    </div>
</div>

И следующий код js:

var $cloned_text = $('.copy_me_text').clone();
$cloned_text.find('input[name="name"]').val("SOMETHING");
$cloned_text.find('input[name="id"]').val("SOMETHING");
console.log($cloned_text.html());

var $cloned_hidden = $('.copy_me_hidden').clone();
$cloned_hidden.find('input[name="name"]').val("SOMETHING");
$cloned_hidden.find('input[name="id"]').val("SOMETHING");
console.log($cloned_hidden.html());

И вывод для меня странный:

<div>
    <input name="name" type="text">
    <input value="SOMETHING" name="id" type="hidden">
</div>
<div>
    <input value="SOMETHING" name="name" type="hidden">
    <input value="SOMETHING" name="id" type="hidden">
</div>

Я также создаю пример jsFiddle . Это правильное поведение? Я не понимаю, почему в функции .html() значение input type="text" не возвращается.

4b9b3361

Ответ 1

Это не странное поведение jQuery, его странный эффект DOM. jQuery.val() не делает ничего, кроме установки свойства value элемента <input>. Под "свойством" я имею в виду свойство DOM, а не атрибут node - см. .prop() vs .attr() для разницы.

Метод .html(), который возвращает innerHTML сериализации DOM, как ожидается, будут отображаться только атрибуты элементов - их свойства не имеют значения. Это поведение по умолчанию, и когда вам нужны сериализованные значения ввода, вам необходимо явно указать их как атрибуты - $input.attr("value", $input.prop("value")).

Итак, почему простая val() работала над скрытыми элементами ввода? Причина в спецификации HTML. Есть отражающие атрибуты IDL, где свойство DOM связано с атрибутом node, но атрибут value не является ничем. Тем не менее, атрибут IDL имеет специальные режимы, в которых он реагирует по-разному. Чтобы привести спецификацию:

Атрибут находится в одном из следующих режимов, которые определяют его поведение:

Значение

При получении, он должен вернуть текущее значение этого элемента. При настройке он должен установить значение значение элемента для нового значения, установить элемент грязное значение [... и сделать много других вещей].

по умолчанию

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

[ "default/on" и "filename" mode]

Определите разницу? А теперь давайте посмотрим на states тип атрибута. И действительно, если мы проверим разделы "Детали бухгалтерского учета", мы заметим, что в hidden state,

Атрибут value IDL применяется к этому элементу и находится в режиме по умолчанию

& тир; в то время как во всех других (текстовых) состояниях режим "значение".


TL; DR:

(Только) В элементах <input type="hidden"> установка свойства value DOM (input.value = …, $input.val(…), $input.prop("value", …)) также устанавливает атрибут value и делает его сериализуемым для innerHTML/.html().

Ответ 2

Это, безусловно, выглядит как ошибка в jQuery. Вы можете заставить его вернуться с помощью функции attr():

$cloned_text.find('input[name="name"]').attr('value', "SOMETHING");

См. обновленный Fiddle

Ответ 3

Функция html() вернет назначение html элементу. В вашем случае вы назначаете значение для ввода текстового поля.

Попробуйте это

$cloned_text.find('input[name="name"]').attr('value', "SOMETHING");

Ответ 4

Это не ошибка jQuery.

Как вы можете видеть в исходном коде jQuery для метода val, они просто устанавливают value в input, что отличается от добавления нового атрибута к элементу (который в конце приводит к изменению свойства value).

Источник jQuery (hooks в этом контексте имеет значение null):

if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
    this.value = val;
}

Итак, чтобы получить то, что вам нужно, вам нужно добавить новый атрибут val к элементу, используя

.attr('value', "SOMETHING");

как упоминалось ранее.

Используя .attr, новый атрибут будет добавлен к элементу, а .html вернет его как строку.

Ответ 5

Хорошим обходным решением этой проблемы будет использование функции attr() вместо val().

Итак, вместо

$cloned_text.find('input[name="name"]').val("SOMETHING");

Запись

$cloned_text.find('input[name="name"]').attr("value", "SOMETHING");