6

I want to store the initial data of my input fields (to be able to check against these initial values later on). Therefore, I use the following code snippet when my page loads:

$(document).ready(function () {
    $('input').data('initial-value', $(this).val() )
}

The problem is that the above does not store the initial value of the input field in a data attribute initial-value. The attribute is not created.

The following does work:

$('input').data('initial-value', 'whatever value' )

Can't I use the jQuery $(this) operator inside the .data() method? If so, what else could I do?

Ze Jibe
  • 989
  • 2
  • 11
  • 29
  • 1
    When you use jQuery's `data` method, it doesn't update the attribute value, but it *does* associate the data with the element. [See my answer to a related question for more details](http://stackoverflow.com/questions/7261619/jquery-data-vs-attr/7262427#7262427). – zzzzBov Apr 01 '13 at 14:24

5 Answers5

9

You will need some iteration for that, and .each will also set the correct this reference for you:

$('input').each(function() {
    $.data(this, 'initial-value', this.value);
});

Fiddle

I've used the static $.data method which provides better performance, but you can use $(this).data('initial-value', this.value) as well.

Also, this.value will do nicely and provides much better performance than $(this).val() - the drawback is when you have select element with the multiple property for which .val() returns an array with the selected values while .value returns the first value only.


Though, you can get the initial value through the element's defaultValue property. E.g.:

console.log( $('input')[0].defaultValue );

Fiddle

Note that this approach will not work for select elements. This would require iterating over the select's option elements and checking their defaultSelected property, but in that case it is easier to go with the former solution.

Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
4

In this case, this refers to the global object since there is no context.

Besides, you don't need this. Just .attr("value") will give you the initial value ;)

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • OK thanks - but I have other fields like `textarea` that do not contain the `value` attribute, for which I'd like to store the initial value. How would I do it then? Besides - just for my understanding - how could I get the context inside the `.data()` method? – Ze Jibe Apr 01 '13 at 14:23
  • Well, you could use `.each`, as this will assign each item to the current context. – Niet the Dark Absol Apr 01 '13 at 14:30
1

How about something like this

$('input').each(function(){$(this).data('initial-value',$(this).val());})
Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141
1

For starters, the code you provided won't work because this refers to document instead of the input element. You'd need to update your code to be:

jQuery(function ($) { //aliasing document.ready shortcut, good practice
    "use strict";
    $('input').data('initial-value', $('input').val());
});

Of course, that probably won't do what you want either, as it will set every input element to store the initial value of the first input element (.val() returns the value of the first matched element).

So to update the code to work for every element, you'd use:

jQuery(function ($) {
    "use strict";
    $('input').each(function () {
        $(this).data('initial-value', $(this).val());
    });
});

But then we need to get into the question of why you're bothering to store the initial value of the element in the first place. If someone changes the value of the input element with $(someElement).val('new value');, the input can be reset by setting its value back to it's [value] attribute:

$(someElement).val($(someElement).attr('value'));

If, on the other hand, you're setting the value of the input element with $(someElement).attr('value', 'new value');, you're doing it wrong, and are corrupting your input element's state. reset buttons rely on the [value] attribute preserving the original state so that when a form is reset, the inputs can be returned to their original state.

You also mentioned:

The problem is that the above does not store the initial value of the input field in a data attribute initial-value. The attribute is not created.

When you use .data() to access data on an element, it will pull information from [data-*] attributes if [data-*] attributes are present. This is great for initializing data on an element.

When you use .data(key, value) to associate data with an element, it will store the value as a property on the element; It will not update the attribute's value. There isn't a way to serialize instantiated objects such as new Foo in a way that it could be deserialized to the way it was originally.

If you want to verify that an object's data was set correctly, you can't simply use the DOM inspector, you'd need to actually check the contents of .data() for that particular element.

For more information about the differences between .attr() and .data(), see my answer to this related question.

Community
  • 1
  • 1
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
1

This does not really work 100%. What you need to do as well is to check whether your form acutally uses input or radio boxes or not.

Check out this solution:

$(':input').each(function() { 
    $(this).data('initialValue', getValueForElement($(this))); 
});

fuunction getValueForElement(oObj) {
    var sValue = oObj.val();
    if (oObj.is(":checkbox") || oObj.is(":radio")) {
        sValue = oObj.is(":checked") ? oObj.val() : ' ';
    }
    return sValue;
}
Gert
  • 51
  • 2