When creating a div dynamically, the children number is wrong

Viewed 33

I have a problem and I can't find any solution. When I click on a button, it creates a div with input and another button as a children. At the first and second click no error occurs. But at the third click an error happens.It creates the third div but it multiples the children of the first div and in the fourth click it adds another child to the first and second div. I want it to creat a normal number of divs and children.

There is my code. Try it to see the problem .

var secondContainer = $(".second-container");
var input1 = $('<input class="bot-section border border-secondary" type="text" name="" value="" disabled>');
var button1 = $('<button class="remove-btn btn btn-outline-danger " type="button" name="button">-</button>');
var add = 1;

$("#adding-btn").click(function() {
  let newDiv = $("#second-container").last().append('<div class="new"></div>');
  $(".new").append(input1);
  $(".new").append(button1);
});
.my {
  text-align: center;
  margin-top: 100px;
  font-family: 'Akaya Telivigala', cursive;
  font-size: 3.7rem;
}

input[type=text] {
  font-family: 'Kufam', sans-serif;
  padding:10px;
  border:0;
  box-shadow:0 0 15px 4px rgba(0,0,0,0.06);
  font-size: 20px;
}

.container {
  margin: 0 auto;
  text-align: center;
  background-color: #D1D1D1;
  width: 35%!important;
}

.inpt {
  margin: 35px auto 8px -3px;
  height: 42px;
  width: 350px;
  background-color: #1A1A40;
  color: white;
  /* padding:10px;
  border-radius:10px; */
}

#adding-btn {
  margin-top: -3px!important;
  margin-left: -3px;
}

/* the section will be added */

.bot-section {
  position: relative;
  margin-left: -5px;
  height: 42px;
  width: 350px;
  background-color: #F7F7F7;
  color: black;
}

.remove-btn {
    /* position: absolute; */
    margin-top: -3px;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>to do list</title>
  <link rel="stylesheet" href="index.css">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Akaya+Telivigala&family=Kufam&display=swap" rel="stylesheet">
</head>

<body>
  <h1 class="my">My to do list</h1>
  <div class="container">
    <div class="top-section">
      <input id="inputField" class="inpt" type="text" name="" value="">
      <button id="adding-btn"  class="btn btn-info" type="button" name="button">+</button>
    </div>
    <div id="second-container">

    </div>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="index.js" charset="utf-8"></script>
</body>

</html>

1 Answers

In your line

$(".new").append 

it selects all .new in the document, not just the newly added one.

Equally, when you use $(selector).append(... it returns the selector, not the new div.

You can create the div first, or you can change .append(..new..) to $(..new..).appendTo and it will return the newly created div, so that you could either chain or append to only that new div

$("#adding-btn").click(function(){
  let newDiv = $('<div class="new"></div>');
  $("#second-container").last().append(newDiv);
  newDiv.append(input1);
  newDiv.append(button1);
});
$("#adding-btn").click(function(){
  let newDiv = $('<div class="new"></div>').appendTo($("#second-container").last());
  newDiv.append(input1);
  newDiv.append(button1);
});

In addition, you are pre-creating your sub-elements with

var input1 = $("...html...");
var button1 = $("...html...");

these will create a single element (for each), so when you use .append(input1) it will move the element into the new newDiv.

You can see this here, where each new .new is a red box and the inputs move to the last container each time instead of creating new ones.

You could clone() these each time

newDiv.append(input1.clone())

but the simpler solution is to not create these as nodes (in memory) in the first instance and instead use plain html.

Updated snippet:

var secondContainer = $(".second-container");
var input1 = '<input class="bot-section border border-secondary" type="text" name="" value="" disabled>';
var button1 = '<button class="remove-btn btn btn-outline-danger " type="button" name="button">-</button>';
var add = 1;

$("#adding-btn").click(function(){
  let newDiv = $('<div class="new"></div>');
  $("#second-container").last().append(newDiv);
  newDiv.append(input1);
  newDiv.append(button1);
});
.my{
  text-align: center;
  margin-top: 100px;
  font-family: 'Akaya Telivigala', cursive;
  font-size: 3.7rem;
}


.container{
  margin: 0 auto;
  text-align: center;
  background-color: #D1D1D1;
  width: 35%!important;
}


#adding-btn{
  margin-top: -3px!important;
  margin-left: -3px;
}

/* the section will be added */

.remove-btn{
  /* position: absolute; */
  margin-top: -3px;
}
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <link href="https://fonts.googleapis.com/css2?family=Akaya+Telivigala&family=Kufam&display=swap" rel="stylesheet">

    <h1 class="my">My to do list</h1>
    <div class="container">
      <div class="top-section">
        <input id="inputField" class="inpt" type="text" name="" value="">
        <button id="adding-btn" class="btn btn-info" type="button" name="button">+</button>
      </div>
      <div id="second-container">
      </div>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


Additional note, will need to use event delegation for your remove button.

Related