Home > OS >  Filter html elements based on data attribute
Filter html elements based on data attribute

Time:08-10

I have the following html structure

<div id="container">
    <div id="child_1" data-customId="100">
    </div>
    <div id="child_2" data-customId="100">
    </div>
    <div id="child_3" data-customId="100">
    </div>
    <div id="child_4" data-customId="20">
    </div>
    <div id="child_5" data-customId="323">
    </div>
    <div id="child_6" data-customId="14">
    </div>
</div>

And what I want to do is to get the count of child divs that contains different data attribute. For example, I'm trying this:

$(`div[id*="child_"]`).length); // => 6

But that code is returning 6 and what I want to retrieve is 4, based on the different data-customId. So my question is, how can I add a filter/map to that selector that I already have but taking into consideration that is a data-attribute.

I was trying to do something like this:

var divs = $(`div[id*="child_"]`);
var count = divs.map(div => div.data-customId).length;

CodePudding user response:

After you getting the child-divs map their customid and just get the length of unique values:

let divs = document.querySelectorAll(`div[id*="child_"]`);
let idCustoms = [...divs].map(div=>div.dataset.customid);
//idCustoms: ["100", "100", "100", "20", "323", "14"]
//get unique values with Set 
console.log([... new Set(idCustoms)].length);//4
//or with filter
console.log(idCustoms.filter((item, i, ar) => ar.indexOf(item) === i).length);//4
<div id="container">
    <div id="child_1" data-customId="100">
    </div>
    <div id="child_2" data-customId="100">
    </div>
    <div id="child_3" data-customId="100">
    </div>
    <div id="child_4" data-customId="20">
    </div>
    <div id="child_5" data-customId="323">
    </div>
    <div id="child_6" data-customId="14">
    </div>
</div>

Note: $ is equivalent to document.querySelectorAll in js returns a NodeList that's why I destructure it by the three dots ...

CodePudding user response:

You'll have to extract the attribute value from each, then count up the number of uniques.

const { size } = new Set(
  $('[data-customId]').map((_, elm) => elm.dataset.customid)
);
console.log(size);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
    <div id="child_1" data-customId="100">
    </div>
    <div id="child_2" data-customId="100">
    </div>
    <div id="child_3" data-customId="100">
    </div>
    <div id="child_4" data-customId="20">
    </div>
    <div id="child_5" data-customId="323">
    </div>
    <div id="child_6" data-customId="14">
    </div>
</div>

No need for jQuery for something this trivial, though.

const { size } = new Set(
  [...document.querySelectorAll('[data-customId]')].map(elm => elm.dataset.customid)
);
console.log(size);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
    <div id="child_1" data-customId="100">
    </div>
    <div id="child_2" data-customId="100">
    </div>
    <div id="child_3" data-customId="100">
    </div>
    <div id="child_4" data-customId="20">
    </div>
    <div id="child_5" data-customId="323">
    </div>
    <div id="child_6" data-customId="14">
    </div>
</div>

Note that the property customid is lower-cased in the JavaScript. This could be an easy point of confusion. You might consider changing your HTML from

data-customId="14"

to

data-custom-id="14"

so that you can use customId in the JS (to follow the common conventions).

  • Related