20

Description:

I am using simple javascript to set a the value of an input. I am using multiple methods that appear to be the same but with different results. Here is an example:

HTML:

<input name="testinput" value="" type="text" />

Javascript:

var input = document.getElementByTagName('input')[0];
input.value = "5"

console.log(input.value) // returns "5"
console.log(input.getAttribute("value")) // returns ""

Of course the functionality is reversed when using the setAttribute() function. Yet, when on form submit they both give a input=5 result.

Question:

What is the point of separating the two properties? is the .value stored differently than the .getAttribute("value")?

Disclaimer:

I have read:

Both of those question/answers left me confused and unsatisfied.

Phil
  • 10,948
  • 17
  • 69
  • 101
  • see also [Properties and Attributes in HTML](http://stackoverflow.com/q/6003819/1048572) – Bergi Apr 07 '16 at 08:54

2 Answers2

27

input.value is dot notation, it sets the value property of the input object.

It does in no way update any attributes, so trying to get an attribute with the same name will not return the updated value.

If for some reason you have to update the attribute, you would do

input.setAttribute('value', 'new_value');

but you shouldn't have to use that, as you generally should be working with the properties, not the attributes, and you'd set and get the value property, not the attribute.


An attribute in HTML is a key / value pair inside the opening and closing brackets, as in

<div attribute="attribute_value"></div>

In many cases such attributes will set the initial value of the underlying property, and the property is a named key with a value, that is attached to the internal model of an element, which is what we access with javascript, the object holding the model and data for the element.

Changing any of that objects keys or values does not change the HTML, only the internal representation of the element, the object. However, changing the HTML attributes will in some cases change the object representation of the element.

getAttribute gets the actual attributes from the HTML, not the properties, while element.value clearly accesses a named property in the object representing that element.

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Your edit is exactly what I was looking for. I wasn't separating the internal object with the html object. – Phil Mar 03 '14 at 16:28
  • @Phil - Attributes and properties can be hard to grok, and in many cases they seem like the same thing as they are so tightly bound together, but they really are two different things, and as shown they can have different names and values even if they seem to represent the same thing. – adeneo Mar 03 '14 at 16:30
  • Follow up question, if I use `document.createElement()` add a attribute to that and `append()` it to the page, would that be treated like an `html` object or would it just be an internal object? – Phil Mar 03 '14 at 16:35
  • If you add an attribute, as in use setAttribute, it's treated as a HTML attribute, but if you set the property, it's on the internal object. You can just test it out, see this -> http://jsfiddle.net/9VfyE/ – adeneo Mar 03 '14 at 17:07
  • 1
    I like the explanation above. May I add that MDN's documentation backs this up with encouragement to use properties instead of .attribute or setAttribute() whenever applicable: https://developer.mozilla.org/en-US/docs/Web/API/Element.setAttribute – Will Klein Mar 03 '14 at 17:29
  • "Changing any of that objects keys or values does not change the HTML" - not quite; setting `input.defaultValue = 'blah';` changes the HTML representation of that element. – Ja͢ck Mar 03 '14 at 20:47
14

It's important to take note of the differences between attributes and properties.

The value attribute

The value attribute of an <input>, visible in the HTML representation of the element, is mapped to the defaultValue property. For example:

var i = document.createElement('input');
i.setAttribute('value', 'foo');
console.log(i.defaultValue, i.getAttribute('value')); // "foo foo"

i.defaultValue = 'bar';
console.log(i.defaultValue, i.getAttribute('value')); // "bar bar"

The value property

The value property mirrors the defaultValue property (and value attribute) until it's explicitly been given a value, so:

var i = document.createElement('input');
i.defaultValue = 'foo';
console.log(i.value); // "foo"

i.value = 'bar';
i.defaultValue = 'foo';
console.log(i.value); // "bar"

This is another way of looking at it:

<input value="foo">
       ↑↓
input.defaultValue = "foo";
        ↓
input.value
  get(): value === undefined ? input.defaultValue : value
  set(newValue): value := newValue

Anchors

When using anchors, the href attribute and href property update each other, but in a different way, e.g.:

var a = document.createElement('a');
a.setAttribute('href', '/test');
console.log(a.href); // "http://stackoverflow.com/test"

a.href = '/test';
console.log(a.getAttribute('href')); // "/test"

Other elements

Here's a (partial) list of attributes and their corresponding properties:

element  | attribute | property
---------+-----------+----------------
option   | selected  | defaultSelected (bool)
label    | for       | htmlFor
input    | checked   | defaultChecked (bool)
select   | multiple  | multiple (bool)
li       | value     | value (int)

As you can see, whereas the attributes are always strings, the corresponding properties may be of other types.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • very well explained. and I didn't know there was a progression of assignments. very cool and thank you! – Phil Mar 03 '14 at 16:28
  • 1
    @Phil Actually, I didn't explain it well enough .. updated the answer :) – Ja͢ck Mar 03 '14 at 16:38
  • This is interesting to read! Interestingly, last week I had some code which was setting `.value` for an `li` element created with `createElement`. The `value` attribute was correctly set... but the value was being parsed as an integer! When I switched to `setAttribute`, the problem disappeared. (The value fields were GUIDs pulled from a database.) I don't have the code any more as that was prototyping some functionality; now my attributes are being bound with knockout.js, but the revelation was surprising. – Brian S Mar 03 '14 at 23:26
  • 1
    @BrianS Right, because the `value` is used in conjunction with `
      ` to indicate what number the bullet point should have :) funny
    – Ja͢ck Mar 04 '14 at 01:28