Your todoDelete()
function is only called after a to do item is created and it is within that function that all the items are found and given their delete
event handler. So the first click gives the element you just clicked on its handler and the second click allows that handler to run, deleting the element.
Instead, the handler should be set prior to the element being created. This can be done through "event delegation", whereby you set the handler up on an ancestor of all the elements and allow the event to bubble up to that element to be handled there. Since that element will exist from the start, it's no problem to set it up on it. Then, when the event is triggered by a dynamically added element later, the event bubbles up to the ancestor, is handled there and in the handler, the actual source of the event is determined. If it is the right source, then you act appropriately. If not, do nothing. This approach not only allows for dynamically added or removed elements to immediately participate in the event handling, but it results in just a single event handler registration, rather than one for each dynamically added element, which is more efficient and easier to keep track of.
Additionally:
So here's your code again, using this approach (see additional comments inline):
const todoAdd = document.getElementById("buttonAdd");
const output = document.getElementById("todoMissions");
// When you are going to need to use the same element
// over and over, just get the reference just once and
// keep using it.
const input = document.getElementById("input");
// Set up the delete handler on an ancestor of all the potential items
document.querySelector(".todo").addEventListener("click", todoDelete);
//ADD
todoAdd.addEventListener("click", () => {
// Best to test this first and then only do the work if there is a value.
if(input.value == ""){
alert("You must write something!");
}else{
var p = document.createElement("p");
// Use the .classList API when setting/removing/toggling
// classes instead of .setAttribute as the API is more straight-forward
p.classList.add("mission");
// No need to create a text node and then inject that into your string
// just inject the string value right into the string.
p.innerHTML = `${input.value} <button class="buttonDelete"><i class="fas fa-trash trash">X</i>`;
output.appendChild(p);
}
input.value = "";
});
//DELETE
function todoDelete(event){
// Look at the event argument and see if the event
// was triggered by a todo item delete button or the
// <i> element within one.
if(event.target.classList.contains("buttonDelete")
|| event.target.classList.contains("trash")){
event.target.closest("p").remove(); // Remove the nearest ancestor p
}
}
<div class="todo">
<input id="input" type="text" maxlength="30" placeholder="text...">
<button id="buttonAdd"><i class="fas fa-pen pencil">Add</i></button>
<div id="todoMissions"></div>
</div>