Edit: turns out nothing is actually wrong with the second snippet (my real code). On one page it works, and on another it doesn’t. Yea for underlying errors.
I’m creating a DOM element and giving that DOM element to a WeakMap as a key. Then, with JQuery event delegation/event listener, I’m trying to retrieve the saved key but it’s returning undefined:
const item = document.createElement("div"), __data = new WeakMap(); __data.set(item, {hello: "123"}) document.body.appendChild(item) // later on in event delegation $("div").on("click", function(event) { const target = event.target, data = __data.get(target); console.log(data) // prints undefined
Anyone know what’s wrong or an alternative method to save data for a DOM element that doesn’t have an ID?
Edit: I’m kinda annoyed that the example I made works but my own code doesn’t… (some bits look redundant. This is modeled after my actual code, so not all the missing pieces are here, just pragmatically) but here’s the apparently working code:
const __data = new WeakMap(); function buildingItem() { const item = document.createElement("div"); item.setAttribute("data-action", "delete"); __data.set(item, {hi: 123}); return item; } function build() { const main = document.getElementById("main") for (let i = 0; i < 3; i++) { const container = document.createElement("div"), attached = document.createElement("div"); const build = buildingItem(), data = __data.get(build); build.classList.add("classified"); data["hello"] = `Item ${i}` __data.set(build, data); build.innerText = `Item ${i}` attached.append(build); container.append(attached); main.append(container); } } build() $(document).on("click", "div.classified[data-action]", function(event) { const target = event.currentTarget, data = __data.get(target); console.log(`CTarget Data: ${data["hello"]}`) })
<div id="main"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Advertisement
Answer
Two possible issues:
target
is the innermost element that was clicked. You probably wantthis
orevent.currentTarget
instead, which is the element on which you hooked the event handler (which may be an ancestor element totarget
).Your jQuery code hooks up the
click
event on all div elements, not just that one, but you only have that onediv
in theWeakMap
. If you click a different div, you’ll naturally getundefined
because that otherdiv
isn’t a key in the map.
Here’s an example (I’ve added a span
within the div
we have in the map to demonstrate #1, and also added a second div
to demonstrate #2):
const item = document.createElement("div"), __data = new WeakMap(); __data.set(item, {hello: "123"}); document.body.appendChild(item); item.insertAdjacentHTML("beforeend", "<span>Click me, I'll work</span>"); document.body.insertAdjacentHTML("beforeend", "<div>Click me, I won't work (I'm not a key in the map)</div>"); $("div").on("click", function(event) { const target = event.currentTarget, data = __data.get(target); console.log("with currentTarget:", data); // Note that using `event.target` wouldn't hav eworked console.log("with target:", __data.get(event.target)); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You’ve mentioned that in your real code you’re using event delegation. currentTarget
and this
are both fine in that case as well:
// Event delegation $(document.body).on("click", "div.example", function(event) { const data1 = __data.get(event.currentTarget); console.log("using currentTarget:", data1); const data2 = __data.get(this); console.log("using this:", data2); }); // Adding the relevant `div` const item = document.createElement("div"), __data = new WeakMap(); __data.set(item, {hello: "123"}); item.className = "example"; item.textContent = "Some text to make div clickable"; document.body.appendChild(item);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>