I have following 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>
And following js code:
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());
And output is strange for me:
<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>
I create also jsFiddle example.
Is it correct behavior? I don't understand, why in .html()
function, value of input type="text"
is not returned.
This is not a strange jQuery behavior, its a strange DOM effect. jQuery.val()
does nothing else than setting the value
property of <input>
element. By "property", I mean the DOM property and not the node attribute - see .prop() vs .attr() for the difference.
The .html()
method, which returns the innerHTML
serialisation of the DOM, is expected to show only attributes of the elements - their properties are irrelevant. This is the default behaviour, and when you want input values serialized you need to explicitly set them as attributes - $input.attr("value", $input.prop("value"))
.
So why did simple val()
work on the hidden input elements? The reason is the HTML specification. There are reflecting IDL attributes, where the DOM property is coupled with the node attribute, but the value
attribute is none of those. Yet, the value IDL attribute has special modes, in which it reacts differently. To cite the spec:
The attribute is in one of the following modes, which define its behavior:
value
On getting, it must return the current value of the element. On setting, it must set the element's value to the new value, set the element's dirty value [… and do a lot of other stuff].
default
On getting, if the element has a value attribute, it must return that attribute's value; otherwise, it must return the empty string. On setting, it must set the element's value attribute to the new value.
["default/on" and "filename" modes]
Spot the difference? And now, let's have a look at the states of the type attribute. And really, if we check the Bookkeeping details sections, we can notice that in the hidden
state,
The
value
IDL attribute applies to this element and is in mode default
‐ while in all other (textual) states the mode is "value".
(Only) On <input type="hidden">
elements, setting the value
DOM property (input.value = …
, $input.val(…)
, $input.prop("value", …)
) also sets the value
attribute and makes it serializable for innerHTML
/.html()
.
That certainly looks like a bug in jQuery. You can force it to return by using the attr()
function:
$cloned_text.find('input[name="name"]').attr('value', "SOMETHING");
See the updated Fiddle
The html()
function will return the html assign to the element. In your case you are assigning value to input text field.
Try this
$cloned_text.find('input[name="name"]').attr('value', "SOMETHING");
It's not a jQuery bug.
As you can see in jQuery source code for the val
method, they're just setting the value
of the input
element, which is a different thing from adding a new attribute to the element (which at the end, results in the value
property change).
jQuery source (hooks
is null in this context):
if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
this.value = val;
}
So, to get what you what, you have to add a new val
attribute to the element, using
.attr('value', "SOMETHING");
as others mentioned.
By using .attr
the new attribute will be added to the element, and .html
will return that as string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With