user3541631
user3541631

Reputation: 4008

Acquiring the JSON value of a data attribute, and search for matching Json key -> data attribute in a specific DOM element

I have an HTML element with a data attribute:

<a href="#" data-trigger="{ "rem": "albatros", "ap":1 }'">Remove</a>
<div data-container>
    <p>lorem ipsum<p>
    <p data-rem></p>
</div>

1.

in the data-trigger sometimes(not always) I send a value:

I want to gather all elements that have the attribute data-trigger:

document.querySelectorAll(['data-trigger']).forEach(function (trigger, index) {

and for each of this trigger to get the DOM and JSON value and parse it:

dom = trigger    
value = JSON.parse(trigger.getAttribute('data-trigger'));

I get the DOM reference but for the value I always get null

By using getAttribute do I call again in the DOM ?

  1. Looping thru data-container search for elements which have the attributes one of the keys found in JSON.parse and set their value, the value of the key.

For example:

<p data-rem>albatros</p>

Upvotes: 0

Views: 1898

Answers (2)

alexP
alexP

Reputation: 3765

This is not valid JSON String

<a href="#" data-trigger="{'rem': 'albatros'}">Remove</a>

Try:

<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a> <!-- Double quotes in JSON -->

Then:

document.querySelectorAll("[data-trigger]").forEach(function (trigger, index) {
  var val = JSON.parse(trigger.getAttribute('data-trigger'));
  for( key in val){ //Loop through (JSON-)Object
  	setInnerElements(val[key], key);
  }
  
});

function setInnerElements(val,key){

document.querySelectorAll("[data-container] > [data-"+ key +"]").forEach(function (el, index) {
  	el.innerHTML = val;
  })
}
<a href="#" data-trigger='{"rem": "albatros", "foo":"test1", "bar":"test2"}'>Remove</a>
<div data-container>
<p>lorem ipsum<p>
<p data-rem></p>
<p>lorem ipsum<p>
<p data-foo></p>
<p>lorem ipsum<p>
<p data-bar></p>
</div>

Upvotes: 2

tao
tao

Reputation: 90237

What is currently stopping your script in its tracks is the selector inside querySelectorAll().

It should be '[data-trigger]', not ['data-trigger'].

After you fix it, you'll be able to get all elements with a data-trigger attribute. However, the string you placed in data-trigger attribute won't parse as a JavaScript object (as you probably expect). Your best bet would be to replace quotes with double quotes and double quotes with quotes, making it a valid JSON string and parse it:

<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a>
JSON.parse(elem.getAttribute('data-trigger')) // where elem is the DOM element above

You haven't been exactly clear on what the purpose of this script is but, assuming you want to find a list of DOM elements having 'data-'+foundKey equal to foundVal, you could make the following selector:

document.querySelectorAll('[data-'+foundKey+'="'+foundVal+'"]').forEach(function(el, i){
  console.log(el, i);
})

... but in your case that wouldn't do anything, because you don't have any element with

<x data-rem="albatros"></x>

Here's a working example of what I'm talking about, applied to your markup:

document.querySelectorAll('[data-trigger]').forEach(function (trigger, index) {
  const triggerProp = JSON.parse(trigger.getAttribute('data-trigger')),
        foundKey = Object.keys(triggerProp)[0],
        foundVal = triggerProp[Object.keys(triggerProp)[0]],
        targets = document.querySelectorAll('[data-'+foundKey+']').forEach(function(target, index) {
    console.log(target, 'key:'+foundKey, 'val:'+target.getAttribute('data-'+foundKey));
  });
})
<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a>
<div data-container>
    <p>lorem ipsum<p>
    <p data-rem="test"></p>
</div>

Do note that it only works because the value of data-trigger is valid JSON. If it were not, it would fail miserably. You could guard your script from this risk by a try/catch function that would test the value as JSON first. Another alternative is to use a library that parses relaxed JSON.

Upvotes: 2

Related Questions