1

I'm trying to put a delete button on each li using JavaScript and to make an event handler that runs when a button is clicked that removes the li. However when I try to add the handler, I get:

Cannot read property 'addEventListener' of null

I think this is because I am referencing a class that not exist before run the function createbtn. So How can I solve this?

The Code:

I set the variables, put querySelector to buttons because I testing how to do it:

var button = document.getElementById("enter"); var input = document.getElementById("userinput"); var ul = document.querySelector("ul"); var list = document.querySelectorAll ("li"); var buttons = document.querySelector (".btn-danger"); var li = document.createElement("li") 

How I create the button:

function createbtn() { for (var i = 0; i < list.length; i++) { var btn = document.createElement("button"); btn.appendChild(document.createTextNode("Delete")); btn.classList.add("btn", "btn-danger","btn-sm"); list[i].appendChild(btn); } } 

The function I try to run:

function liDel(){ li.parentNode.removeChild(li); } buttons.addEventListener("click", liDel); 

This is my fiddle to see all the code.

1
  • Try creating the button before using the selector. Commented Apr 17, 2018 at 20:25

3 Answers 3

1

The reason why you are getting the null error is because;

  • You have assigned the variable buttons to a node which doesn't exist yet. (Note that the button is created after the page has been loaded, which means .btn-danger hasn't yet been created at that time).
  • According to MDN the querySelector method does the the ff:

    The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.

Based on the code you have in the fiddle, here is a guide to achieve the desired results.

First of all, get rid of the global li variable on line 6. The reason is that if you create a new li from the input, it will render on the same line because it's still referencing the same element node (I'm sure you've realized that)

then in your createListElement function, do the ff

function createListElement() { var li = document.createElement('li'); li.appendChild(document.createTextNode(input.value)); var btn = document.createElement("button"); btn.appendChild(document.createTextNode("Delete")); btn.classList.add("btn", "btn-danger","btn-sm"); btn.addEventListener('click', function(e){ if(!e) e = window.event; try{ ul.removeChild(this.parentNode) }catch(err){ alert(err.message) } }) li.appendChild(btn) ul.appendChild(li); input.value = ""; } 

Then when you create the buttons, you have to attach the event listener function to it. So you do the ff in your createbtn function:

// To create a button function createbtn() { for (var i = 0; i < list.length; i++) { var btn = document.createElement("button"); btn.appendChild(document.createTextNode("Delete")); btn.classList.add("btn", "btn-danger","btn-sm"); btn.addEventListener('click', function(e){ if(!e) e = window.event; try{ ul.removeChild(this.parentNode) }catch(err){ alert(err.message) } }) list[i].appendChild(btn); } } 

anyways, there are more efficient ways to do this. But this is a quick workable model based on the code in your fiddle

Sign up to request clarification or add additional context in comments.

Comments

0

Rather than querying and adding the event to the buttons object try the chaining inside the document load.

window.onload = function () { document.querySelector('.btn-danger').addEventListener('click', liDel); }; 

The above code should work!

Comments

0

Thanks a lot everybody, I got a solution after reading all your answers: First I got rid the following:

var buttons = document.querySelector (".btn-danger"); var li = document.createElement("li") 

Then create this function for remove the "li" Using "this" you avoid the error for don't have a reference, because with that you don't care in what kind of element this is, you only now something is there and grab it for anything you need.

function liDel(){ ul.removeChild(this.parentNode); } 

and put this in createBtn for delete the existing "li" in the html:

btn.addEventListener('click', liDel); 

then put this on createElement for do the same of the above, but for the new "li" creates with the DOM:

btn.addEventListener('click', liDel); li.appendChild(btn); 

And with that the problems was solved.

Thanks again and you can see how the page works on the fiddle

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.