Luiso
Luiso

Reputation: 4113

JQuery not filtering DOM changes

I have a questionnaire page and some div have a data-answered attribute added to them like this:

<div class="question" data-answered="False">
   ... rest of the html
</div>

now I have several of those and at some point, through js (you can read JQuery) I do:

myDiv.data("answered", "True")

please assume I have a way to get the actual div that's not the issue here. Now I can see that the actual data-answered attribute is set to "True" when I check the js locals, the DOM explorer however shows nothing. The issue comes however when I need the answered questions count like this:

var answeredCount = $('[data-answered=True]').length

then no matter how many changes I've made, I always the same elements/results/count as when the page first loaded. However if I do the following:

var answeredCount = $('[data-answered]')
      .filter(function () { return $(this).data('answered') == 'True' })
      .length

then I get the results I expected. I will be adding an image with some data on an actual browser as prove to I have just said to support my claim:

enter image description here

Note: This behavior seems to occur on Opera and Edge, since I tried it on Chrome and it worked as I expected, haven't tried Firefox.

Is this the intended behavior?
Have I misunderstood something about how JQuery works with the DOM and it changes?
Is it something of only these 2 browsers that makes them special?

Upvotes: 0

Views: 58

Answers (3)

fumihwh
fumihwh

Reputation: 1249

Seems every thing goes well.

You could check the document about jQuery .data()

Briefly, $(...).data('answered', 'True') will not change the attr data-answered="False" to data-answered="True". $(...).attr('data-answered', 'True') does.

Upvotes: 1

marmeladze
marmeladze

Reputation: 6564

With raw javascript, you can achieve desired result, by below code. Probably, you have problems because of comparing by True instead of 'True'

var ans = Array.from(document.getElementsByClassName("question")).filter(e=> (e.dataset.answered == 'True') ).length


 /*
 *
 * if your browser does not support ES6 syntax
 * Array.from(document.getElementsByClassName("question")).filter(function(e){ return e.dataset.answered == 'True' } ).length
 * 
 */

document.getElementById('answered').innerHTML = ans;
    <div class="question" data-answered="False">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="True">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="True">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="False">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="True">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="True">
   ... rest of the html
    </div>
    <hr>
    <div class="question" data-answered="False">
   ... rest of the html
    </div>
    <hr>
    <div id="results">
      <p>Answered: <span id="answered"></span></p>
    </div>

Upvotes: 0

luiscrjr
luiscrjr

Reputation: 7258

To handle data- attributes, you should set it whith the .attr method. Like this:

myDiv.attr("data-answered", "True")

Now, $('[data-answered=True]') should work.

That's because .data() stores the data into a internal jQuery place, and doesn't add data- attribute to the DOM.

To retrieve data, in the other hand, .data(key) both returns data assigned with .data(key,value) or the data- attributes. From the docs:

Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.

Upvotes: 1

Related Questions