Patrick Roberts
Patrick Roberts

Reputation: 51957

jQuery grabbing value of a dynamic data-* attribute

Inside of a jQuery click event listener I have some code like this:

function (evt) {
  evt.preventDefault();

  var reportbox = $(this).closest('.activityItem');
  var id = reportbox.data('questionId');
  ...
}

This works fine for data-question-id attributes, but I'm generalizing the function now and I need to grab the value from any of the following:

data-question-id
data-answer-id
data-comment-id
data-user-id
data-company-id

What's the best way to do this?

Upvotes: 1

Views: 980

Answers (3)

Josh Crozier
Josh Crozier

Reputation: 241198

As Brian points out, you could access the dataset property to retrieve all the element's data-* attributes:

$('.activityItem').each(function () {
  var dataAttributes = this.dataset;

  Object.keys(dataAttributes).forEach(function (key) {
    console.log(key, dataAttributes[key]); // key, value
  });
});

Since you only want the first data attribute, you could simply use:

var dataAttributes = this.dataset;
var id = dataAttributes[Object.keys(dataAttributes)[0]];

It's important to note that the dataset property returns the attribute names in camel case without the data prefix. In other words, data-question-id would be questionId.

If you want to retrieve all of an element's attributes, access the attributes property and check which attributes start with data-* and end with -id. It's definitely more verbose, but it may work better in other scenarios.

$('.activityItem').each(function () {
  var attributes = this.attributes;

  Object.keys(attributes).forEach(function (key) {
    var attribute = attributes[key];

    if (/^data-.*-id$/.test(attribute.name)) {
      console.log(attribute.name, attribute.value);
    }
  })
});

Upvotes: 2

Patrick Roberts
Patrick Roberts

Reputation: 51957

I just thought of what I was looking for. I guess my question confused you, but here's what I wanted:

$('#test').children().each(function () {
  var reportbox = $(this);

  var id = reportbox.data(Object.keys(reportbox.data())[0]);
  
  reportbox.text(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
  <div data-question-id="1"></div>
  <div data-answer-id="2"></div>
  <div data-comment-id="3"></div>
  <div data-user-id="4"></div>
  <div data-company-id="5"></div>
</div>

The line of focus being:

var id = reportbox.data(Object.keys(reportbox.data())[0]);

Edit

Alternatively thanks to @Brian's comment I can rewrite this to:

var id = this.dataset(Object.keys(this.dataset)[0]);

Upvotes: 1

bcr
bcr

Reputation: 3811

If you know only one of those attributes will be present and you want to retrieve that single value you can use this:

var element = $(el);
var dataAttrs = ['question-id', 'answer-id', 'comment-id', 'user-id', 'company-id'];
var data = getUnknownAttr(element, dataAttrs);


function getUnknownAttr(element, potentialAttrs) {      
    var $element = element instanceof $ ? element : $(element);
    var result = null;

    potentialAttrs.forEach(function (attr) {
        var temp = $element.data(attr);
        if (typeof temp !== 'undefined') {
            result = temp;
        }
    });

    return result;
}

Upvotes: 2

Related Questions