-1

I want to dynamically create, populate and clear a list with html and javascript. The creation and population of the list work just fine, but when I want to add the delete-button to the list item I can't attach the onclick event to the newly created element. Here is my complete function, it is called every time some changes happen to the printlist array:

var printlist = [];
var awesome = document.createElement("i");
awesome.className = "fa fa-minus";

function addToList(stationid, stationname)
{
    var object = {id: stationid, name: stationname};
    printlist.push(object);
    drawList();
}

function removeFromList(id)
{
    printlist.splice(id, 1);
    drawList();
}

function drawList()
{
    if (printlist.length > 0)
    {
        document.getElementById("printListDialog").style.visibility = 'visible';
        var dlg = document.getElementById("DlgContent");
        dlg.innerHTML = "";
        for (var i = 0; i < printlist.length; i++)
        {
            var item = document.createElement("li");
            item.className = "list-group-item";
            var link = document.createElement("a");
            link.href = "#";
            link.dataset.listnumber = i;
            link.style.color = "red";
            link.style.float = "right";
            link.appendChild(awesome);
            link.onclick = function(){onRemove();};
            item.innerHTML = printlist[i].name + " " + link.outerHTML;
            dlg.appendChild(item);
        }
    }
    else
    {
        document.getElementById("printListDialog").style.visibility = 'hidden';
    }
}

function onRemove(e)
{
    if (!e)
        e = window.event;
    var sender = e.srcElement || e.target;
    removeFromList(sender.dataset.listnumber);
}

I tried:

link.onclick = function(){onRemove();};

as well as

link.addEventListener("click", onRemove);

Neither of those lines successfully adds the event from the script. However when I call any of the 2 lines above from the console it works and the event is attached.

Why does it work from the console but not from the script?

Paedow
  • 3,402
  • 8
  • 35
  • 67
  • 2
    You do realize you can only attach events to elements when they are created. So after you actually placed the element in the DOM. – Leon Feb 19 '18 at 15:00
  • See this https://stackoverflow.com/questions/34896106/attach-event-to-dynamic-elements-in-javascript . You need to attach the event to the document and check if the target is the desired one. – Karmidzhanov Feb 19 '18 at 15:02
  • 3
    Possible duplicate of [Attach event to dynamic elements in javascript](https://stackoverflow.com/questions/34896106/attach-event-to-dynamic-elements-in-javascript) – Liam Feb 19 '18 at 15:02
  • Also relevant [What is DOM Event delegation?](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation) – Liam Feb 19 '18 at 15:02
  • 1
    What is -> `awesome` – Keith Feb 19 '18 at 15:03
  • If you have to ask @Keith you'll never know :) – Liam Feb 19 '18 at 15:04
  • 1
    Should work : https://jsfiddle.net/jnwrc5ay/473/ – Zakaria Acharki Feb 19 '18 at 15:06
  • 3
    @Leon `So after you actually placed the element in the DOM` The element doesn't need to be part of the DOM for you to attach events, but does of course need to be created.. :) – Keith Feb 19 '18 at 15:07
  • I posted my complete script. I came across all solutions suggested in linked questions whilst i was trying to solve this on my own but nothing works. The only thing i haven't tried is document.addEventListener() – Paedow Feb 19 '18 at 15:21
  • @ZakariaAcharki: yes it SHOULD work but for some reason it doesn't – Paedow Feb 19 '18 at 15:22

1 Answers1

1
link.onclick = function(){onRemove();};

doesn't work because you're not passing through the event argument. link.onclick = onRemove should work just as your addEventListener call.

However, both of them don't work because of the line

item.innerHTML = printlist[i].name + " " + link.outerHTML;

which destroys the link element with all its dynamic data like .dataset or .onclick, and forms a raw html string that doesn't contain them. They're lost.

Do not use HTML strings!

Replace the line with

item.appendChild(document.createTextNode(printlist[i].name + " "));
item.appendChild(link); // keeps the element with the installed listener
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • Thank you. replacing the innerhtml line with your 2 lines it works. Every attribute except onclick was present in the resulting node beforehand though. – Paedow Feb 20 '18 at 07:51
  • Ah, right, all the other properties are [reflected as attributes](https://stackoverflow.com/a/6004028/1048572) so they would get picked up by `outerHTML` – Bergi Feb 20 '18 at 16:43