javascripthtmldomchildren

Create element with children inside using appendChild()


I am trying to create a grid layout, where by pressing the button "NEW TARGET", a new target is created besides it. The target is everything in the lightgrey box, both the red boxes and the text saying layout: x by x. The problem I am having is that I don't know how to create a new target with all the children inside.

<!doctype html>
<html>
  <head>
    <title>This is the title of the webpage!</title>
    <link rel="stylesheet" type="text/css" href="Gasflasker udvidet.css" />
  </head>
  <body>
    <div id="target-wrapper" class="target-wrapper">
        <div class="target">
            <p class="archive-title">Layout: 
            <select>
                <option>1</option>
                <option>2</option>
                <option>3</option>
            </select>
            by
            <select>
                <option>1</option>
                <option>2</option>
                <option>3</option>
            </select>
            </p>
        <div class="image" draggable="true">1</div>
        <div class="image" draggable="true">2</div>
        <div class="image" draggable="true">3</div>
        <div class="image" draggable="true">4</div>
        <div class="image" draggable="true">5</div>
        <div class="image" draggable="true">6</div>
        <div class="image" draggable="true">7</div>
        <div class="image" draggable="true">8</div>
        <div class="image" draggable="true">9</div>
    </div>
    </div>
    <button id="button" class="button" onclick="newTarget()">NEW TARGET</button>
  </body>
</html>
<script src="./Gasflasker udvidet.js"></script>
.target-wrapper {
    background-color: black;
    display: flex;
    width: fit-content;
    grid-gap: 10px;
    align-items: center;
    padding: 10px;
}

.target {
    background-color:lightgrey;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    width:fit-content;
    grid-gap: 5px;
    padding: 5px;
}

.archive-title {
    grid-column: 1/4;
}

.image {
    background-color: coral;
    width: 100px;
    height: 100px;
}

.button {
    width: 100px;
    height: 100px;
}
function newTarget() {
const targetWrapper = document.getElementById("target-wrapper");

const target = document.createElement("div");
target.classList.add("target");
targetWrapper.appendChild(target);
};

I tried using appendChild(), but that only lets me create the grey box itself, not it's children as well (at least as far as I know).

Thank you in advance!


Solution

  • Instead of using a div to hold the original, you can use the template tag. Then simply use importNode on document to import the template's content.

    const addTarget = document.querySelector(".addTarget");
    const target = document.querySelector("#target");
    const targetWrapper = document.querySelector("#target-wrapper");
    
    addTarget.addEventListener("click",() => {
      targetWrapper.appendChild(document.importNode(target.content, true));
    });
    .target-wrapper {
        background-color: black;
        display: flex;
        width: fit-content;
        grid-gap: 10px;
        align-items: center;
        padding: 10px;
    }
    
    .target {
        background-color:lightgrey;
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        width:fit-content;
        grid-gap: 5px;
        padding: 5px;
    }
    
    .archive-title {
        grid-column: 1/4;
    }
    
    .image {
        background-color: coral;
        width: 100px;
        height: 100px;
    }
    
    .addTarget{
        width: 100px;
        height: 100px;
    }
    <template id="target">
      <div class="target">
        <p class="archive-title">Layout:
          <select>
            <option>1</option>
            <option>2</option>
            <option>3</option>
          </select>
          by
          <select>
            <option>1</option>
            <option>2</option>
            <option>3</option>
          </select>
        </p>
        <div class="image" draggable="true">1</div>
        <div class="image" draggable="true">2</div>
        <div class="image" draggable="true">3</div>
        <div class="image" draggable="true">4</div>
        <div class="image" draggable="true">5</div>
        <div class="image" draggable="true">6</div>
        <div class="image" draggable="true">7</div>
        <div class="image" draggable="true">8</div>
        <div class="image" draggable="true">9</div>
      </div>
    </template>
    <div id="target-wrapper" class="target-wrapper">
    
    </div>
    
      <button id="button" class="addTarget"> NEW TARGET
        </button>