I'm trying to create variable from a class inside the innerHTML down here:
ruleData.forEach((rule) => {
rulesWrapper.innerHTML = `
<div class='rule'>
<div id='rule-title' class='rule-title' onclick='showRuleDetail(${counter})'>
<div>
<p>${counter}.</p>
<p>${rule.title}</p>
</div>
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.5 5.5L7.5 10.5L12.5 15.5" stroke="#1E1E20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<div class='rule-body'>
<p>${rule.body}</p>
</div>
</div>
`;
counter ;
});
for example i want to target rule-body
class inside this innerHTML and change it's background
like this :
let ruleBody = document.querySelectorAll('.rule-body');
ruleBody[0].style.background = 'red';
but this doesn't work ,i get this error:
TypeError: Cannot read properties of undefined (reading 'style')
CodePudding user response:
You can use DOMParser for this
ruleData.forEach((rule) => {
let rule_html = `
<div class='rule'>
<div id='rule-title' class='rule-title' onclick='showRuleDetail(${counter})'>
<div>
<p>${counter}.</p>
<p>${rule.title}</p>
</div>
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.5 5.5L7.5 10.5L12.5 15.5" stroke="#1E1E20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<div class='rule-body'>
<p>${rule.body}</p>
</div>
</div>
`;
let rule = new DOMParser().parseFromString(rule_html,"text/xml").firstChild;
rule.querySelector('.rule-body').style.background = 'red';
rulesWrapper.appendChild(rule);
counter ;
});
Also if the counter is the index of the ruleData you can use forEach's index as well. (rule,i)=>{
CodePudding user response:
You must access the .rule-body
after the innerHTML and make sure it is indeed in the DOM. Then, this should work perfectly fine:
const container = document.querySelector("#container");
const button = document.querySelector("#button");
function exec() {
container.innerHTML = `<div class='rule-body'>yo</div>`;
const ruleBody = document.querySelectorAll('.rule-body');
ruleBody[0].style.backgroundColor = 'red';
}
button.onclick = exec;
<div id="container">
</div>
<button id="button">
CLICK TO INSERT
</button>
CodePudding user response:
I suggest to map and delegate
const ruleData = [{"title":"Title 1","body":"This is the body"},{"title":"Title 2","body":"This is the body"}]
const rulesWrapper = document.getElementById("rulesWrapper");
rulesWrapper.innerHTML = ruleData.map((rule,i) => `
<div class='rule'>
<div class='rule-title' data-idx='${i}'>
<div>
<p>${i}.</p>
<p>${rule.title}</p>
</div>
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.5 5.5L7.5 10.5L12.5 15.5" stroke="#1E1E20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<div class='rule-body'>
<p>${rule.body}</p>
</div>
</div>
`).join("");
rulesWrapper.addEventListener("click", function(e) {
const tgt=e.target.closest(".rule-title");
if (tgt) console.log(tgt.dataset.idx)
})
<div id="rulesWrapper"></div>