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"
не возвращается.
Ответы
Ответ 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");