Mine was a problem with a React app. I was loading an SVG icon sheet using XHR, and dynamically prepend it to the <body>
tag's content. This was done lazily, the first time an Icon was rendered.
I was trying to put a grid of actions, each of which has an icon, into an Accordion component. The accordion would work with any other content, but when I added the icon grid, it would just not respond. I first started looking for the cause by inserting an SVG in the accordion directly, without the <use>
SVG tag, and that worked. Then I loaded my sprite sheet, and inserted a <svg><use ... /></svg>
tag, and it stopped working. I was tearing my head out, until at one point while having lunch, the cause popped into my head. Here's how I was fetching and inserting my sprite sheet:
fetch(location.origin + "/api/icons", {/* ... options ...*/}).then((resp) => {
return resp.text();
}).then((svg) => {
document.body.innerHTML = svg + document.body.innerHTML;
});
The problem was that doing this removes all the event listeners from the page, as you're basically recreating the entire DOM from a string.
Here's what my code looks like now:
fetch(location.origin + "/api/icons", {/* ... */}).then((resp) => {
return resp.text()
}).then((txt) => {
let div = document.createElement("div");
div.innerHTML = txt;
document.body.insertBefore(div.firstChild, document.body.firstChild)
});
So I'm inserting the SVG I get from the server as text into a newly created div element. Then, I insert the contents of that div, right before the first tag in the body. The important thing, is that I'm actually inserting the SVG element as a DOM node, not as text. This way, the DOM stays intact, and the event handlers still work. hurray! 🎉
Now it's time to tell your stories from the debugging battlefield.