Is it possible to attach a click event to a document fragment?

The click event will not work in this case because document fragment is not appended to DOM structure. Here is what documentation says about it:

Various other methods can take a document fragment as an argument (e.g., any Node interface methods such as Node.appendChild and Node.insertBefore), in which case the children of the fragment are appended or inserted, not the fragment itself.

So "children of the fragment are appended, not fragment itself". It means that click event bound to fragment is pretty much useless, because being outside of the DOM it's not reachable for clicks.


There are two things preventing your code from working

Events and DocumentFragment

First, as @dfsq said, the value of container is a DocumentFragment. When you call appendChild later, the contents of the DocumentFragment are moved into the DOM, but the fragment itself is not. That means the event listener is "left behind", and won't ever be triggered by a click.

The solution is to attach the event listener to one of the children of container, like headline:

headline.addEventListener('click', ...

Often you don't have a direct reference, like if you're working with templates and .cloneNode. In many cases the fragment only contains one element, so using container.firstElementChild is a good way to go. If your fragment were more complex, you might need to use .querySelector or something similar.

container.appendChild(headline);
container.firstElementChild.addEventListener('click', // ...

DocumentFragment and .appendChild

Second, when you call document.body.appendChild the contents of the DocumentFragment are moved into the DOM, and out of the fragment. The fragment doesn't retain a reference. The idea is that a node can't have two parents. That means that by the time you call addEventListener, there aren't any nodes for events to happen to!

The solution is to attach the event listener before calling .appendChild.

Solution

Putting these two together gives the following implementation:

// creating elements
var container = document.createDocumentFragment();
var headline = document.createElement('h1');
headline.innerHTML = 'This is a headline.';

// attaching click event
headline.addEventListener('click', function () {
    console.log('click happened!');
});

// attaching to DOM
container.appendChild(headline);
document.body.appendChild(container);

Tags:

Javascript