skip to Main Content

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!

3

Answers


  1. You can make use of the cloneNode method to clone the element along with its children and then append it like you were doing

    Note: the only issue with this is that it will also clone the id from your element, leading to having multiple elements with the same id in some cases. This won’t be a problem for you tho, since we are cloning a div with no id, it has a class target, so no issues there. But if you ever run into that you can just change the id of the cloned element. for example:

    let cloneElement = div.cloneNode(true);//clone the element
    cloneElement.id = 'another-id';//give it a new id
    

    Full code

    const targetWrapper = document.getElementById("target-wrapper");
    
    function newTarget() {
      const div = document.querySelector(".target");
      let cloneElement = div.cloneNode(true);
      targetWrapper.appendChild(cloneElement);
    };
    .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;
    }
    <!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>
    Login or Signup to reply.
  2. 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>
    Login or Signup to reply.
  3. Copy the target element, including its children with .cloneNode(true) method, and add it to the targetWrapper element:

      const cloneTarget = document.querySelector(".target").cloneNode(true);
      document.querySelector("#target-wrapper").appendChild(cloneTarget);
    

    DEMO:

    function newTarget() {
      const targetWrapper = document.querySelector("#target-wrapper");
      const target = document.querySelector(".target");
      const cloneTarget = target.cloneNode(true);
      targetWrapper.appendChild(cloneTarget);
    };
    .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;
    }
    <div id="target-wrapper" class="target-wrapper">
      <div class="target">
        <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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search