6

I've been checking many and many posts here in stackoverflow but, even if many solutions should be working, it yet doesn't work for me.

I have a modal in bootstrap where I have a list of bootstrap checkboxes (<label><input> style).

Each checkbox has a set of data attributes that are directly setted from an AJAX request and, therefore, that aren't settet through jQuery.

In my situation, I need to remove all the data-attr from the checkbox when it is toggled and add some other.

The problem, however, is that I'm being unable to remove them.

I've first tried using jQuery.removeData(), but then I've read that it actually only removes data attributes if at least one of them has been set through jQuery, therefore it is not my case.

So, I've checked a little bit around and found out that I should be using jQuery.removeAttr() prototype and remove each data element.

So, my case is this one:

$('.modal_day_checkbox').on('change', function(){
        if ($(this).is(':checked')) {
            removeAllData($(this));
            $(this).data('newid', 'test_id');
            console.log($(this).data());
        }
        else {
            removeAllData($(this));
            $(this).data('testID', 'ID_NEW');
            console.log($(this).data());
        }
    });

And, in order to have a clean code, I've implemented the function removeAllData:

function removeAllData(object) {
        $.each(object.data(), function(i, v) {
            object.removeAttr("data-"+i);
            console.log('removing: '+'data-'+i);
        });
    }

Which is just looping through the object to check what data attributes it has and it should be removing it.

Surprisingly, the result is this one:

Any idea?

14
  • If someone is still reading the question, the solution is, as proposed by @Alnitak, to replace .removeAttr with .removeData, providing the index [i] of the each loop! Commented Jul 31, 2014 at 16:06
  • according to the docs you would use the name of the data, not its index. And actually I was just proposing that you both call your own function and object.removeData() to ensure that both the cache and the HTML attributes are removed. Commented Jul 31, 2014 at 16:09
  • It the data attributes are, as you said, not added by jQuery, why would you need removeData, which removes data from the internal jQuery data object ? Commented Jul 31, 2014 at 16:12
  • Ah, the index being referred to was actually a key, not a number. That works, but you can just call .removeData() with no keys and get them all in one go. Commented Jul 31, 2014 at 16:12
  • @adeneo in my experience, any access to the data attributes causes the cache to be created, it's not just creation that does this. Commented Jul 31, 2014 at 16:13

3 Answers 3

6

Try calling the jQuery .removeData function as well as your removeAllData function:

function removeAllData(object) {
    $.each(object.data(), function(i, v) {
        object.removeAttr("data-"+i);
        console.log('removing: '+'data-'+i);
    });
    object.removeData();  // clear the cache too
}

jQuery maintains a separate object where data-foo values are cached as soon as they're access (and where writes to .data are stored) and that cache is not cleared when you call .removeAttr('data-foo').

Sign up to request clarification or add additional context in comments.

3 Comments

You mean that I should replace .removeAttr with .removeData?
Yes, but don't append the data- prefix. Just object.removeData(i)
Indeed, tried it and actually works.. Damn, I was so close :P Thanks! I'll accept the answer as soon as the system allows me to, I have to wait 8 minutes :)
1

Chosen solution works great, but will break on multi-dash attributes (like data-one-two) because:

Since jQuery 3, every two-character sequence of "-" (U+002D) followed by a lowercase ASCII letter in a key is replaced by the uppercase version of the letter, in alignment with the HTML dataset API. A statement like $( "body" ).data( { "my-name": "aValue" } ).data(); will return { myName: "aValue" }.

source

To make results of data() work with removeAttr() we should cast them back to normal:

function removeAllData(object) {
    $.each(object.data(), function(i, v) {
        i = i.replace(/([A-Z])/g, function(all, letter) {
            return '-' + letter.toLowerCase()
        });  // fix multi-dash attributes
        object.removeAttr("data-"+i);
        console.log('removing: '+'data-'+i);
    });
    object.removeData();  // clear the cache too
}

It's not an ideal solution, but should work in most cases.

Comments

-1

this is wrong

object.removeAttr("data-"+i);

// you have to pass in the name of the attribute

Do this instead

 $.each(object.data(), function(i, v) {
            object.removeAttr(v);
            console.log('removing: '+v);
        });

// Removed quote

1 Comment

Sorry, this doesn't work. It throws me an Uncaught InvalidCharacterError. Thanks for downvoting both the question and the answer above anyway

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.