Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Injecting into nested DOM elements created with template literals

I have a fairly simple question. I need to create a list of items that is quite deeply nested, something of this sort (in reality every div has like 20+ classes, data-attributes and so forth):

<div class="one" data-foo="a x y z">
  <div class="two" data-bar="x y z">
    <ul class="three" data-foobar="a b c">
    // contents
    </ul>
  </div>
</div>

My current code is:

    const div1 = document.createElement("div");
    div1.classList.add("one", all the other classes);
    div1.setAttribute("data-foo", "lots of data attributes");
    
    const div2 = document.createElement("div");
    div2.classList.add("two", all the other classes);
    div2.setAttribute("data-bar", "lots of data attributes");
    
    const div3 = document.createElement("div");
    div3.classList.add("three", all the other classes);
    div3.setAttribute("data-foobar", "lots of data attributes");

    div1.appendChild(div2);
    div2.appendChild(div3);

    // getting items for the list & other code

    div3.appendChild(someOutputData);

I came up with a great idea of using a template literal so I don’t have to add all the extra properties, classes etc. I know it seems like I could’ve fixed it with simple foreach but there are bazillion of other things like aria tags etc. etc.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

So my old code becomes:

 const wrapper = document.createElement("div");
 const layout = `<div class="one" data-foo="a x y z">
   <div class="two" data-bar="x y z">
     <ul class="three" data-foobar="a b c">
        
     </ul>
   </div>
 </div>`;

wrapper.innerHTML = layout;
wrapper.appendChild(someOutputData);

Million times clearer, right?

The problem is wrapper.appendChild(someOutputData); is not longer injecting data into .three but into <div> wrapper that is above .one.

Is there some way I can target nested DOM elements created via template literals? How can I push my someOutputData (list of nodes) into .three using the second snippet? Also can I omit wrapper somehow? I don’t really need the "div" around my list.

>Solution :

So use variables in your template and select the element you created to append the elements

function createComponent(data1, data2, data3, listData) {
  const wrapper = document.createElement("div");
  const layout = `<div class="one" data-foo="${data1}">
    <div class="two" data-bar="${data2}">
      <ul class="three" data-foobar="${data3}">
        
      </ul>
    </div>
  </div>`;

  wrapper.innerHTML = layout;
  wrapper.querySelector("ul").append(...listData);

  return wrapper;
}


const makeLi = (text) => {
  const li = document.createElement('li');
  li.textContent = text;
  return li;
};

const lis = ['foo', 'bar'].map(makeLi);
const elem = createComponent(1,2,3, lis);
document.body.append(elem);


const lis2 = [1,2,3,4,5].map(makeLi);
const elem2 = createComponent(1,2,3, lis2);
document.body.append(elem2);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading