Reputation: 4187
I am trying to delete an element in a ul (list item) like so using only javascript. since I am dynamically generating the html, I am trying to set the onclick as I create it below. However when I try to click (see fiddle) elements are not getting deleted. relevant functions below:
var appendHTML = function (el) {
var list = document.getElementById("events");
for (var i = 0; i < filteredDates.length; i++) {
var listItem = filteredDates[i].name;
listItem.className = "event-list";
listItem.setAttribute("onclick", "deleteEvent()");
list.appendChild(listItem);
}
};
var deleteEvent = function () {
var listItem = this.parentNode;
var ul = listItem.parentNode;
//Remove the parent list item from the ul
ul.removeChild(listItem);
return false;
};
https://jsfiddle.net/youngfreezy/7jLswj9b/5/
Upvotes: 0
Views: 110
Reputation: 816422
There are a couple of things wrong with your jsFiddle and your code.
You are using an inline event handler. Inline event handlers are executed in global scope. However, because the fiddle by default wraps your JavaScript code inside a function, deleteEvent
is not global. The console shows the error:
Uncaught TypeError: Cannot read property 'appendChild' of null
There are three ways to solve this:
this
inside the event handlerBecause you are calling the function as deleteEvent()
, this
won't refer to the DOM element that triggered the event. It will refer to window
, the global object, which doesn't have a parentNode
property.
If you use a different way to bind the handler, as suggested above, then that problem might solve itself. Otherwise, you have to call deleteEvent
in such a way that this
refers to the element:
onclick="deleteEvent.call(this)"
Of course you could also change the definition of deleteEvent
to accept the element as argument instead.
However, in your fiddle you actually attached the event handler to the <ul>
element, not to each <li>
element. In that case you have to pass the event object to function instead and get the original target from it:
onclick="deleteEvent(event)"
and
var deleteEvent = function (event) {
//Remove the parent list item from the ul
event.target.parentNode.removeChild(event);
}
It seems you are deleting the wrong node in deleteEvent
. listItem
will actually be the <ul>
element, because that's the parent of the clicked element. Consequently, ul
will be the parent of the <ul>
element.
Since this
already refers to the <li>
element, there is need for listItem
here, and ul
should be this.parentNode
. In shorter form:
var deleteEvent = function () {
//Remove the parent list item from the ul
this.parentNode.removeChild(this);
}
return false
has no effectreturn false
is often used to prevent the default action of the event. However, clicking on a li
element has no default action. Furthermore, the value has to be return from the event handler. deleteEvent
is not your event handler, it is called by your event handler. So if you want to return its return value, you have to do exactly that:
listItem.setAttribute("onclick", "return deleteEvent()");
But again, you should prefer a different of binding the event handler.
In the code in your question you are trying to call setAttribute
on an arbitrary object and try to append an arbitrary object to a DOM element. That won't work. You have to use document.createElement
to create a new element:
var li = document.createElement('li');
It seems you are doing this correctly in your fiddle.
Upvotes: 1
Reputation: 3341
If you use the onclick
attribute to set event code as a string, the this
context gets lost.
The best way to register event handlers is via addEventListener
:
listItem.addEventListener("click", deleteEvent);
As a fallback, set your event code as a function instead:
listItem.onclick = deleteEvent;
This is discouraged as you can only set 1 event handler per event this way.
If you really really have to set the code Inline, pass the value of this
via an argument:
<ul id="events" onclick="deleteEvent(this)">...</ul>
function deleteEvent(element) {
// ...
}
Upvotes: 1
Reputation: 2306
Your first problem was that you had the "deleteEvent" in your html, jsFiddle doesn't like it.
second problem was that you took the wrong element in the deleteEvent so the parent was incorrect as well.
See updated fiddle: https://jsfiddle.net/7jLswj9b/7/
var deleteEvent = function (ev) {
var listItem = ev.target;
var ul = listItem.parentNode;
//Remove the parent list item from the ul
ul.removeChild(listItem);
return false;
}
var list = document.getElementById("events");
list.addEventListener("click",deleteEvent,false);
Upvotes: 5