Eon
Eon

Reputation: 3974

The value returned from a custom attribute is undefined

I am avoiding the use of $(this).attr() to get the values of custom elements, and I have read up that should you need a custom element, you should prefix it with data- and use $(this).data() to access the contents of that element (in my case, it is dynamically populated into the element as the element is part of a set of dynamic elements)

My question is fairly simple.

<a id="' + node.Id + '" data-currentValue='+node.Name+' class="button icon-pencil with-tooltip" href="javascript:void(0);" title="Edit" onclick="UpdateAttributes($(this).data(\'currentValue\'), $(this).attr(\'id\'));"</a>

I logged the values to the console after capturing them, but unsurprisingly, the $(this).data() part returns undefined (value should be in this tested case "asdf") , and the id returns the value I expected it to return (in my case, 2000046).

What is wrong with this element? I cannot spot where things have gone wrong, I have no idea why it throws undefined, and I need the value within data-currentValue. Any Ideas and insights to share so I can get the value I need from data-currentValue?

Dynamic element as a whole:

    $("#tblAttributes tbody").empty();
    var tableContents = [];
    $.each(data.KeyValuePairs, function (i, node) {
        tableContents[tableContents.length] = '<tr>';
        tableContents[tableContents.length] = '<td>';
        tableContents[tableContents.length] = '<p>';
        tableContents[tableContents.length] = node.Name;
        tableContents[tableContents.length] = '</p>';
        tableContents[tableContents.length] = '</td>';
        tableContents[tableContents.length] = '<td>';
        tableContents[tableContents.length] = '<span class="button-group compact">';
        tableContents[tableContents.length] = '<a id="' + node.Id + '" data-currentValue='+node.Name+' class="button icon-pencil with-tooltip" href="javascript:void(0);" title="Edit" onclick="UpdateAttributes($(this).data(\'currentValue\'), $(this).attr(\'id\'));"</a>';
        tableContents[tableContents.length] = '<a id="' + node.Id + '" class="button red-gradient icon-trash with-tooltip confirm" href="javascript:DeleteAttribute('+node.Id+');" title="Delete" </a>';
        tableContents[tableContents.length] = '</span>';
        tableContents[tableContents.length] = '</td>';
        tableContents[tableContents.length] = '</tr>';
    });
    $("#AttributeCount").html(data.KeyValuePairs.length);
    $("#tblAttributes tbody").append(tableContents.join(""));

Edit

So this approach I had in mind was clumsy and cumbersome (thanks to BlazeMonger confirming that .data() tries to convert everything to primitive types, so I have changed my code to use an associative array instead to access the information where I need it. I no longer need custom attributes in the elements.

var attributes = {}; //associative array declared globally
...


$("#tblAttributes tbody").empty();
    var tableContents = [];
    attributes = {};
    $.each(data.KeyValuePairs, function (i, node) {
        attributes[node.Id] = node; //associating the node's id with the node for future use
        tableContents[tableContents.length] = '<tr>';
        tableContents[tableContents.length] = '<td>';
        tableContents[tableContents.length] = '<p>';
        tableContents[tableContents.length] = node.Name;
        tableContents[tableContents.length] = '</p>';
        tableContents[tableContents.length] = '</td>';
        tableContents[tableContents.length] = '<td>';
        tableContents[tableContents.length] = '<span class="button-group compact">';
        tableContents[tableContents.length] = '<a id="' + node.Id + '" class="button icon-pencil with-tooltip" href="javascript:void(0);" title="Edit" onclick="UpdateAttributes(' + node.Id +');"</a>';
        tableContents[tableContents.length] = '<a id="' + node.Id + '" class="button red-gradient icon-trash with-tooltip confirm" href="javascript:DeleteAttribute('+node.Id+');" title="Delete" </a>';
        tableContents[tableContents.length] = '</span>';
        tableContents[tableContents.length] = '</td>';
        tableContents[tableContents.length] = '</tr>';
    });
...
        function UpdateAttributes( attrId) {
        console.log(attributes[attrId].Name); //now I can access the information I needed which was to be stored as a custom attribute in the <a> element.

Upvotes: 0

Views: 1370

Answers (1)

Blazemonger
Blazemonger

Reputation: 92893

The .data() method retrieves the data- HTML attributes once, at page load. After that, you can alter the data- attributes but it won't change what's retrieved by data().

Instead, use .data(name,value) to set new values that .data(name) will retrieve. (Note also that this will not alter the data- HTML attributes at the same time. You can change one or the other.)

It might be useful for jQuery to have some way to automatically pull the current data- attributes into data() variables at once, but as of jQuery 1.9 no such built-in functionality exists. Shouldn't be hard to write one, though.

http://api.jquery.com/data/

Upvotes: 2

Related Questions