How to get, set and select elements with data attributes?
Asked Answered
E

4

25

I'm having some trouble with data-attributes, I can't get anything to work for some reason so I must be doing something wrong:

Set:

$('#element').data('data1', '1'); //Actually in my case the data is been added manually 

Does that make a difference?

Get:

$('#element').data('data1');

Select:

$('#element[data1 = 1]')

None of this works for me, am I making this up or how is it?

Estipulate answered 7/11, 2012 at 18:25 Comment(2)
Maybe related to #13095277.Ornamentation
You shouldn't need to set the [data-*] attribute from within JavaScript.Gailey
D
55

All of the answers are correct, but I want to state something that nobody else did.
The jQuery data method acts like a getter for html5 data attributes, but the setter does not alter the data-* attribute.
So, If you manually added the data (as is stated in your comment), then you can use a css attribute selector to select your element :

$('#element[data-data1=1]')  

but if you have added (altered) the data via jQuery, then the above solution won't work.
Here's an example of this failure :

var div = $('<div />').data('key','value');
alert(div.data('key') == div.attr('data-key'));// it will be false  

So the workaround is to filter the collection by checking the jQuery data value to match the desired one :

// replace key & value with own strings
$('selector').filter(function(i, el){
    return $(this).data('key') == 'value';
});

So, in order to overcome these issues, you need to use the html5 dataset attributes (via jQuery's attr methos) as getters and setters :

$('selector').attr('data-' + key, value);

or you can use a custom expression that filters jQuery internal data :

$.expr[':'].data = function(elem, index, m) {
    // Remove ":data(" and the trailing ")" from the match, as these parts aren't needed:
    m[0] = m[0].replace(/:data\(|\)$/g, '');
    var regex = new RegExp('([\'"]?)((?:\\\\\\1|.)+?)\\1(,|$)', 'g'),
    // Retrieve data key:
    key = regex.exec( m[0] )[2],
    // Retrieve data value to test against:
    val = regex.exec( m[0] );
    if (val) {
        val = val[2];
    }
    // If a value was passed then we test for it, otherwise we test that the value evaluates to true:
    return val ? $(elem).data(key) == val : !!$(elem).data(key);
};

and use it like :

$('selector:data(key,value)')

Update

I know this thread is a few years old, but since it has some activity, it's worth mentioning that doing this using the querySelector dom API (with no need for jQuery) is quite trivial:

document.querySelectorAll('[attribute=value]')
Dumyat answered 7/11, 2012 at 18:46 Comment(4)
this is where part of my problem was coming from I think what I'm actually looking for is just using attributes instead of data that way I don't have this problem, Thanks gion!Estipulate
Thanks gion that answer is very complete and covers everythingEstipulate
Hi @Dumyat The filter method works for me but I cant seem to get the custom expression to work. Maybe due to jQuery changes? Would you mind having a look at jsfiddle.net/DelightedDoD/jqLa7q81/2 ?Compulsive
Apparently, after jQuery 1.7.2, the value that is returned for m is different than it was when gion_13 wrote the above custom expression. Here is a version that will work up to at least jQuery 2.1.3 jsfiddle.net/DelightedDoD/bbbb0shuCompulsive
C
10

To reflect the values of the Attributes immediately in the DOM you can use .attr()

$('#element').attr('data-data1', '1');  // Sets the attribute

$('#element[data-data1="1"]') // Selects the element with data-data1 attribute'

$('#element').data('data1'); // Gets the value  of the attribute

$('#element').attr('data-data1'); // Gets the value  of the attribute

In plain Javascript you can try this

var elem = document.getElementById('element');

elem.setAttribute('data-data1', '1'); // Set the attribute

elem.getAttribute('data-data1'); // Gets the attribute
Caribbean answered 7/11, 2012 at 18:31 Comment(1)
I think using the attr() is going to be the best way for me thanks it works now.Estipulate
F
5
// Set
$('#element').attr('data-value', 'value');
// Get
var value = $('#element').attr('data-value');
// Select
var elem = $('#element[data-value = "' +value+ '"]');
Franglais answered 7/11, 2012 at 18:34 Comment(0)
B
1

You are using ID selector so there is no need to use attribute selector, as data is a property and you are setting it using data method (not attr method) you cannot select the element using attribute selector, if you want to select the element only if it has data1 === 1 you can use the filter method:

(function($){
    $(function(){
       // ...
       $('#element').filter(function() {
          return this.dataset.data1 == 1
          // return $(this).data('data1') == 1
       })
    })
})(jQuery);

dataset: Allows access, both in reading and writing mode, to all the custom data attributes (data-*) set on the element. It is a map of DOMString, one entry for each custom data attribute.

Brammer answered 7/11, 2012 at 18:29 Comment(1)
I just used an id selector in this made up example, I'm acually using a class selector. I will check that filter function out now, thanks for your help.Estipulate

© 2022 - 2024 — McMap. All rights reserved.