0

I'm having a strange problem. I'm trying to make a program that will add and delete div's inside another div called "body". To add divs, I use document.getElementById("body").innerHTML. Adding works fine. However, in the deleting function, I replace the "body" id with a variable with the id of the div that will be deleted. But when I run the code, I get the error "cannot set innerHTML of null". I tried to replace the id variable with a fixed local variable, and it worked fine. I also tried to add quotes to the variable but that didn't work either. Is there any reason why I can't set the id to a changing variable? Thanks.

Here is my code:

var i = 1;

function myFunction() {
  var addDiv = document.getElementById("body2");
  addDiv.innerHTML += "<div id = '" + i + "'><br><textarea id = '1' > foo < /textarea></div > ";
  i++;
}

function myFunction2() {
  var deleteDiv = document.getElementById(i);
  deleteDiv.innerHTML = "";
  i--;
}
<div id="body2">
  <div id="0">
    <textarea id="text">lol</textarea><button onclick="myFunction()">Add</button>
    <button onclick="myFunction2()">Delete</button>
  </div>
</div>
Rajesh
  • 24,354
  • 5
  • 48
  • 79
Mister_Maybe
  • 137
  • 1
  • 1
  • 14
  • just as an aside, document.getElementById("body").innerHTML can be shortened to document.body.innerHTML https://developer.mozilla.org/en-US/docs/Web/API/Document/body –  Jul 18 '17 at 13:22
  • it is not really recommended to use raw numeric values as ids (which should be unique in the whole page). I recommend using a prefix, like `id = 'myprefix_"+i+"'` – Kaddath Jul 18 '17 at 13:22

2 Answers2

2

you are incrementing i after adding a div so you must use i-1 while deleting to get correct id.

var i = 1;

function myFunction() {
var addDiv = document.getElementById("body2");
addDiv.innerHTML += "<div id = '"+i+"'><br><textarea id = '1'>foo</textarea></div>";
i++;
}

function myFunction2() {
var deleteDiv = document.getElementById(i-1);
deleteDiv.remove();
i--;
}
<div id = "body2">
<div id = "0">
   <textarea id = "text">lol</textarea><button onclick = 
   "myFunction()">Add</button>
    <button onclick = "myFunction2()">Delete</button>
</div>
</div>
Dij
  • 9,761
  • 4
  • 18
  • 35
  • I tried your solution, but after adding and subtracting several times, it stops working and deletes them out of order. – Mister_Maybe Jul 18 '17 at 13:30
  • that was because of `deleteDiv.innerHTML = "";`, I missed it earlier, you need to use `deleteDiv.remove()` instead, i have updated code, seems to work now. – Dij Jul 18 '17 at 13:36
1

To remove last child, you can even use CSS selector last-child. You should also add specific class to newly added divs as you would want to remove only newly added divs.

This will also remove dependency of i.

As an addon, you can also use document.createElement + Node.appendChild instead of setting innerHTML. .innerHTMl will be expensive for highly nested structure.

function myFunction() {
  document.getElementById("body2").appendChild(getDiv());
}

function getDiv(i){
  var div = document.createElement('div');
  div.classList.add('inner')
  var ta = document.createElement('textarea');
  ta.textContent = 'foo';
  div.appendChild(ta);
  return div;
}

function myFunction2() {
  var div = document.querySelector('#body2 div.inner:last-child')
  div && div.remove()
}
<div id="body2">
  <div id="0">
    <textarea id="text">lol</textarea><button onclick="myFunction()">Add</button>
    <button onclick="myFunction2()">Delete</button>
  </div>
</div>

You can refer "innerHTML += ..." vs "appendChild(txtNode)" for more information.

Rajesh
  • 24,354
  • 5
  • 48
  • 79