I’m making an expense tracker with HTML, CSS, and JavaScript and I ran into a problem where when I first load up the page I can add as many div items I want, but then after I delete one (or more) of them, the adding button doesn’t work anymore. The error I get in the console is:
main.js:8 Uncaught TypeError: Cannot read properties of null (reading ‘appendChild’) at HTMLButtonElement.duplicate (main.js:8:25).
I have a function for removing a div (in this case the div is the expense item in the list), called deleteItem(), and another one for adding a div, called duplicate(). I’m not sure what is happening, but if anyone can help, that would be great.
I’ve seen a few possible solutions on YouTube that use JQuery, but since I’m still learning JavaScript, I’m trying not to get into that just yet. However, if the solution requires JQuery or anything like that, let me know.
document.getElementById('new-item-btn').onclick = duplicate;
var original = document.getElementById('expense-item');
function duplicate() {
var clone = original.cloneNode(true);
clone.id = "expense-item";
original.parentNode.appendChild(clone);
}
function deleteItem() {
var removeItem = document.getElementById('expense-item');
removeItem.remove();
}
<main id="main">
<div class="container" id="container">
<div class="expense-item" id="expense-item">
<button class="delete-btn" onclick="deleteItem()">Delete</button>
<div class="expense-inputs">
<label for="expense-name"></label>
<input type="text" placeholder="Expense Name" id="expense-name">
<label for="expense-category"></label>
<select name="expense-category" id="expense-category">
<option value="">Category</option>
<option value="groceries">Groceries</option>
<option value="housing">Housing</option>
<option value="utilities">Utilities</option>
</select>
<label for="expense-amount"></label>
<input type="text" id="expense-amount" name="expense-amount" placeholder="Amount">
</div>
</div>
</div>
<div class="info">
<div class="new-item">
<button class="new-item-btn" id="new-item-btn" onclick="duplicate()">New Item</button>
</div>
</div>
</main>
2
Answers
What you can do to make the delete method dynamic and work without id is:
Then you just need to add
this
toonclick="deleteItem()"
Note I would advice you to still change the id to something new on the create but this is the example of the delete method.
demo
You can, in most instances, remove IDs when creating dynamic content and use other means of identifying DOM nodes – such as
querySelector
in combination withevent.target.
Inspecting anEvent
to determine the origin of the click is probably the most reliable method.The dynamically added content does not know in advance IDs or other attributes so by supplying the
event
as an argument to thedeleteItem
method you can identify the newly added content from button to container and remove it quite easily.