JQuery.prop () returns undefined, while .attr () works as expected for data- *

I'm just trying to get a couple of properties from two elements. Getting the value property from an input element works as expected. The problem is getting the data-detail property of the property from the button element. It returns undefined when using .prop() , but works as expected when using .attr() .

Can someone explain this strange behavior that I observe?

HTML

 <div class="formRow"> <label for="firstName">First name</label> <div class="detailsControlBtns"> <button id="editFirstName" class="btn ctaBtn greenBtn editBtn">Edit</button> <button class="btn ctaBtn greenBtn saveBtn" data-detail="firstName">Save</button> <button id="closeFirstName" class="btn ctaBtn greyBtn closeBtn">Close</button> </div> <input type="text" id="firstName" name="firstName" value="[+firstName+]" readonly> </div> 

Js

 $(".saveBtn").on("click", function() { var saveBtn = $(this); // The following statement yields undefined. When using .attr() it works as expected. var detail = saveBtn.prop("data-detail"); var relevantInput = saveBtn.parent().next(); // The following statement works as expected. var value = relevantInput.prop("value"); // ... }); 
+5
source share
1 answer

This is because there is no data-detail property in the HTML element.

Here is a brief description . data () , .prop () and . attr () :

The DOM is an object that has methods and properties (from the DOM ) and attributes (from the HTML rendering). Some of these properties get their initial value using attributes
id->id, class->className, title->title, style->style etc.

Consider this element: <input type="checkbox" checked data-detail="somedata" >

Result of the following:

 $('input').prop('id'); // => " "-empty string, property id exist on the element (defined by DOM) , but is not set. $('input').attr('id');// => undefined - doesn't exist. 


If you do the following:
 $('input').attr('id',"someID"); $('input').prop('id'); // => "someID" $('input').attr('id'); // => "someID" 

And:

 $('input').prop('id',"someOtherID"); $('input').prop('id');// => "someOtherID" $('input').attr('id');// => "someOtherID" 

So, some attributes and properties have a 1: 1 mapping . (change change result attr, etc.).


Consider the following: <input type="text" data-detail="somedata" value="someValue">
 $('input').prop('value'); // => "someValue" $('input').val(); // => "someValue" $('input').attr('value'); // => "someValue" 

And if you do:

 $('input').prop('value','newVal'); // or $('input').val('newVal'); $('input').prop('value'); // => "newVal" -value of the property $('input').val(); // => "newVal" -value of the property $('input').attr('value'); // => "someValue" -value of the attr didn't change, since in this case it is not 1:1 mapping (change of the prop value doesn't reflect to the attribute value). 

Case c . data ()

1) How to get:

- Keep in mind that attribute name is data-* and property name is dataset , therefore:

 <input type="checkbox" data-detail="somedata" > 

  $('input')[0].dataset; //=> [object DOMStringMap] { detail: "somedata"} $('input')[0].dataset.detail; // => "somedata" $('input').prop('dataset'); //=>[object DOMStringMap] { detail: "somedata"} $('input').prop('dataset').detail; // => "somedata" $('input').data('detail'); // => "somedata" $('input').attr('data-detail'); // => "somedata" 

2) How to install:

I) $('input').prop('dataset').detail='newData';

  $('input').prop('dataset'); //=> [object DOMStringMap] { detail: "newData"} $('input').prop('dataset').detail; // => "newData" $('input').attr('data-detail'); // => "newData" $('input').data('detail'); // => "newData" 

II) $('input').attr('data-detail','newData');

  $('input').prop('dataset'); //=> [object DOMStringMap] { detail: "newData"} $('input').prop('dataset').detail; // => "newData" $('input').attr('data-detail'); // => "newData" $('input').data('detail'); // => "newData" 

So, you can see that the display is 1: 1, the attr change reflects prop and vice versa.

But check out the third way:

III) $('input').data('detail','newData');

  $('input').prop('dataset'); // => [object DOMStringMap] { detail: "somedata"} $('input').prop('dataset').detail; // => "somedata" $('input').attr('data-detail'); // => "somedata" $('input').data('detail'); // => "newData" <-----****** 

So what is going on here?

$(elem).data(key, value) does not change the HTML5 data-* attributes of the HTML5 data-* element. It stores its values ​​in $.cache internally.

So, to get data-* you will never go wrong in .data() :

 $(".saveBtn").on("click", function() { var saveBtn = $(this); var detail = saveBtn.data("detail"); var relevantInput = saveBtn.parent().next(); var value = relevantInput.prop("value"); }); 
+12
source

Source: https://habr.com/ru/post/1247261/


All Articles