Difference between method ". attr()" and ". date()"

Asked

Viewed 1,581 times

14

I notice that there is a difference between updating or applying an attribute data using the jQuery method .attr() and the method .data().

The examples below can be seen in this Jsfiddle.

  • Apply value to non-existent attribute

    If the value is applied by the method .attr() and then change the same by the method .data(), the result of collecting the value varies according to the method used to apply it:

    <div id="myBanana"></div>
    
    • Apply

      // utilizando .attr()
      $( "#myBanana" ).attr( "data-fail", "no banana" );
      
      // utilizando .data()
      $( "#myBanana" ).data( "fail", "no monkey" );
      
    • Collect

      // utilizando .attr() da "no banana"
      console.log( $( "#myBanana" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "no monkey"
      console.log ( $( "#myBanana" ).data( "fail" ) );
      
  • Apply value to existing attribute

    If the attribute already exists in the widget, when collecting it with any of the methods, I receive the existing value.

    After a change to the value, depending on the method used, the value applied is only correctly collected if you use the same method to obtain it:

    <div id="myMonkey" data-fail="banana"></div>
    
    • Collect

      // utilizando .attr() dá "banana"
      console.log( $( "#myMonkey" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "banana"
      console.log ( $( "#myMonkey" ).data( "fail" ) );
      
    • Alter

      // utilizando .attr()
      $( "#myMonkey" ).attr( "data-fail", "No banana" );
      
      // utilizando .data()
      $( "#myMonkey" ).data( "fail", "More banana" );
      
    • Reapply

      // utilizando .attr() dá "No banana"
      console.log( $( "#myMonkey" ).attr( "data-fail" ) );
      
      // utilizando .data() dá "More banana"
      console.log ( $( "#myMonkey" ).data( "fail" ) );
      

    At first both methods were to collect the same value that was already present in the attribute data, but after changing this value, I have to use the same method to apply and collect values or the results diverge.

It is obvious that the attribute is called data-*, is not directly related to the method .data() but with the method .attr().

In addition both methods seem to interact with the attribute data up to a certain point, but each has its own way of storing new assigned values.

When analyzing what happens in terms of DOM manipulation, there are also noticeable differences substances caused by the use of each of the methods:

Captura de Tela

The method .attr() is actually updating the value of the attribute data while the method .data() does not change the value of the attribute, but attaches an identifier to the element with its value.

Question

What is the difference between the method .attr() and the method .data() in terms of use, purpose and impact on the element, to make use of arbitrary data assignment that HTML5 makes available ?

2 answers

11


The two methods are completely different

.data()

The .data() was created for the purpose of associating arbitrary data to a DOM element. In fact, this method is an interface to the $.data, that is part of the core of jQuery.

The data is stored in an internal object, and there are associated with the DOM element in question. The data does not hang directly on the object representing the element. This is very clear if you look at the source code. With the consolidation of attributes data- in HTML5*, the .data() started reading the HTML attribute if you can’t find an equivalent key.

So don’t consider the .data as a method to handle attributes data-. He is more than that. Moreover, he has two fundamental differences (one of them you pointed out in the question):

  1. When writing data with .data(), the attribute data- corresponding is not affected
  2. If your attribute name contains underscores or hyphens, the .data() apply camelCase in the name before using it as internal key.

.attr()

The .attr() is dedicated to working with attributes. It will always read from an attribute and write in an attribute, ie modifies the DOM, unlike the .data(). Personally, it’s my preferred method for handling attributes data-, especially for not changing the names with camelização as does the .data().


* I’m not so sure about the timeline here

7

The main reason for this behavior was explained in the @bfavaretto answer (difference between the arbitrary data held by jQuery and the attributes data-*), but even though jQuery didn’t do anything special with the data, he still wouldn’t behave in the expected way.

Quoting an answer in the SOEN:

A DOM element is an object, a thing in memory. Like most objects in the POO, it has estates. It also, separately, has a mapping of the attributes defined in the element (generally coming from the Markup browser read to create the element). Some of the estates of the element gain its value initial from the attributes with the same or similar name (value gains its initial value from the "value attribute"; href gains its initial value from the "href" attribute, but is not exactly the same value; className of the "class" attribute). Other properties gain their initial values in other ways: For example, the property parentNode gains its value based on what is its parent element; an element always has a property style, regardless of whether it has a "style" attribute or not.

Previous versions of jQuery mixed attributes with properties, resulting in strange behaviors. From version 1.6 the method has been separated attr of prop (not without some accidents along the way...), so that conceptually doesn’t make much sense if you keep using attr - since in the vast majority of cases what is wanted is prop. Until the version 1.9 these two methods were still kept synchronized, for compatibility reasons, but from then on they were separated for good.

Consider the following Markup:

<input value="foo">

And the following Javascript:

$("input").prop("value", "propriedade");
$("input").attr("value", "atributo");

What will be the value of the text box at the end of the execution? If you run this in jQuery 1.8, it will be "atributo" (because it was assigned last, and whatever use attr or prop). If you use 1.9, it will be "propriedade" (for the attr only modified the Mkup, the DOM object remained unchanged). Example 1, Example 2.

That way, don’t expect the attr keep up to date as the elements in the DOM change, use it only if you want to get the initial state of the same (i.e. what was written in the Markup).


Updating: the behavior of .data today is quite different from what I remembered. I made some additional tests, and now I can understand how it works:

  • If there is no programmatically assigned value through the method .data(chave, valor), then it uses the attribute value data-chave.
    • This applies both to the absence of assignment and to the removal of that value.
  • If it exists, it uses the assigned value - ignoring the attribute.
  • No property data-chave, dataChave, etc..

Example:

<div id="teste" data-foo="10">
$("#teste").data("foo"); // 10

$("#teste").data("foo", 20);
$("#teste").data("foo"); // 20

$("#teste").attr("data-foo", 30);
$("#teste").data("foo"); // ainda 20

$("#teste").removeData("foo");
$("#teste").data("foo"); // 30
  • Interesting, in short the method .attr() gives us the present value in the .data() gives us the value of the Markup when there is no assignment after loading the page, or the current value if already changed! The .prop() since version 1.9 of jQuery assumes the same behavior as the method .data(), got it right?

  • @Zuul actually I’m confused, after I posted the answer I did some more tests and I noticed that the data completely changed its behavior (as the bfavaretto said, this was after HTML5 consolidated the attributes data-*). I’m still not quite sure how he behaves. But anyway, the idea I wanted to pass on in this answer was that the attr refers to the text of the Markup, and the prop refers to a property (field, member) of the object in the FOD.

  • @Zuul (clarifying: the behavior was one last time I checked - around the version 1.6 - and today is another; I had not attempted to that fact when I formulated the answer)

  • 1

    Excellent explanation of attr. Detail: if you set/change the value of an attribute with attr, and then try to read it again with attr, the value read will be the new one. Therefore, the attr not only reads the initial value, it simply combines getAttribute and setAttribute.

  • 1

    @bfavaretto Correct! But the important thing is that the property is not affected by this change. Ex.: type "test" in the text box; use the code $("input").attr("value", "foobar"); after this code, if you look at the text box you will see that its value is still "test". If you use a form submit without Javascript, the value passed will still be "test". That is, even if there is correspondence between the attr of jQuery and the getAttribute and setAttribute of the GIFT, there is no correspondence between them and the property itself.

  • 1

    Interesting, it seems to be a special case of Forms. I tested with rel and href (which I believe are properties), and changing the attribute also changed the property (http://jsfiddle.net/LD3GX/).

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.