Home How to use vanilla JS to query with a single value a data attribute with array of values?
Reply: 3

How to use vanilla JS to query with a single value a data attribute with array of values?

binarymason Published in 2018-01-06 13:18:38Z

I have a series of blog posts that have an array of tags as a data-tags html attribute such as ["foo", "bar", "baz"]. I'm looking to query the DOM elements that have foo included in the data-tags array.

Example markup:

<li data-tags="['foo', 'bar', 'baz']">...</li>

I know it's possible to query if the data attributes were stored as a singular value, ie:


Is it even possible to select elements which arrays include a specific value?

(Vanilla JS only, no jQuery please)

orabis Reply to 2018-01-06 14:31:28Z

To sum up, the query you need is


But you have to make sure that each element in your html array is enlosed within double quotes. You may change it to a single quote, but make sure to update the query.

You can search for multiple queries by adding more rules as follows


Below is a snippet that applies those queries based on some value you may be interested in. I made sure to use the same html structure you put in your question.


I added one more function, queryAll, that allows for value queries. So, you can search for elements that must have more than one value.

function entry(search){
  var string = '"' + search + '"';
  return '[data-tags*=\'' + string + '\']';

function queryAll() {
  var queries = Array.prototype.slice.call(arguments).map(function(a){
    return '[data-tags*=\'' + a + '\']';
  //example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
  return document.querySelectorAll('li'+ queries.join(''));

function query(search) {
  var string = '"' + search + '"';
  //example: document.querySelectorAll('li[data-tags*=\'"foo"\']');
  return document.querySelectorAll('li[data-tags*=\'' + string + '\']');
query("foo1"); // One li
query("foo"); //Two li's

queryAll("foo1", "bar1");  //one li
queryAll("foo1", "bar1Not");  //nothing
  <li data-tags='["foo", "bar", "baz"]'>...</li>
  <li data-tags='["foo1", "bar1", "baz1"]'>...</li>
  <li data-tags='["foo2", "bar2", "baz2"]'>...</li>
  <li data-tags='["foo", "bar2", "baz2"]'>...</li>

kurt Reply to 2018-01-06 13:41:56Z

You can use CSS to get any element on the page.


Get elements with href's [href]

Get divs with data-type of price div[data-type=price]

var attributes = ['data-rel','type'];
<p data-rel="title">World!</p>
<p type="emoji">:-)</p>

neatsu Reply to 2018-01-06 14:19:07Z

Here's a vanilla js solution to your problem:

const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
    if (/foo/.test(post.getAttribute('data-tags'))) {

// output the filtered posts

One liner alternative:

document.querySelectorAll('[data-tags]').forEach(post => /foo/.test(post.getAttribute('data-tags')) && console.log(post));

Or splitted:

document.querySelectorAll('[data-tags]').forEach(post =>
    /foo/.test(post.getAttribute('data-tags')) && console.log(post));

Please, note that, as mentioned in the comments, your html markup is invalid. Data attributes should not contain complex data structure like arrays or objects. As suggested, consider performing a .join() on your array data and outputting it in the attribute [data-tags] as a string. In it each value can be separated by comma for readability.

Using the valid markup your solution will be slightly different:

const posts = document.querySelectorAll('[data-tags]');
const fooPosts = [];
posts.forEach(post => {
    if (post.getAttribute('data-tags').indexOf('foo') > -1) {


The above code is also faster as it's using .indexOf() to filter the DOM nodes. Here's the above code in a reusable function:

const filterNodesByAttr = (attr, tag) => {
    let filtered = [];
    const items = document.querySelectorAll(`[${attr}]`);
    items.forEach(item => {
        if (item.getAttribute(attr).indexOf(tag) > -1) {
    return filtered;

const fooPosts = filterNodesByAttr('data-tags', 'foo');
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.30811 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO